From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Library/BaseCacheMaintenanceLib/ArmCache.c | 241 ++ .../BaseCacheMaintenanceLib.inf | 54 + .../BaseCacheMaintenanceLib.uni | 18 + .../Library/BaseCacheMaintenanceLib/EbcCache.c | 225 ++ .../Library/BaseCacheMaintenanceLib/RiscVCache.c | 250 ++ .../Library/BaseCacheMaintenanceLib/X86Cache.c | 272 ++ .../BaseCacheMaintenanceLibNull.c | 225 ++ .../BaseCacheMaintenanceLibNull.inf | 29 + .../BaseCacheMaintenanceLibNull.uni | 12 + .../Library/BaseCpuLib/AArch64/CpuFlushTlb.S | 32 + .../Library/BaseCpuLib/AArch64/CpuFlushTlb.asm | 33 + .../MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S | 33 + .../MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm | 34 + .../MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S | 30 + .../MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm | 31 + roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S | 37 + .../MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm | 38 + roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf | 69 + roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni | 20 + .../Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c | 40 + .../MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c | 28 + .../Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm | 31 + .../Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c | 26 + .../edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c | 28 + .../MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm | 30 + .../MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c | 27 + roms/edk2/MdePkg/Library/BaseCpuLib/RiscV/Cpu.S | 19 + .../MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm | 32 + .../MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm | 31 + .../MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c | 37 + .../Library/BaseCpuLibNull/BaseCpuLibNull.inf | 26 + .../Library/BaseCpuLibNull/BaseCpuLibNull.uni | 11 + .../Library/BaseDebugLibNull/BaseDebugLibNull.inf | 31 + .../Library/BaseDebugLibNull/BaseDebugLibNull.uni | 16 + .../MdePkg/Library/BaseDebugLibNull/DebugLib.c | 246 ++ .../BaseDebugLibSerialPort.inf | 44 + .../BaseDebugLibSerialPort.uni | 16 + .../Library/BaseDebugLibSerialPort/DebugLib.c | 374 ++ .../BaseDebugPrintErrorLevelLib.c | 53 + .../BaseDebugPrintErrorLevelLib.inf | 35 + .../BaseDebugPrintErrorLevelLib.uni | 16 + .../BaseExtractGuidedSectionLib.c | 478 +++ .../BaseExtractGuidedSectionLib.inf | 49 + .../BaseExtractGuidedSectionLib.uni | 22 + .../BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S | 142 + .../BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm | 143 + .../Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S | 141 + .../Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm | 145 + .../BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf | 69 + .../BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni | 19 + .../BaseIoLibIntrinsicArmVirt.inf | 46 + .../BaseIoLibIntrinsicArmVirt.uni | 17 + .../BaseIoLibIntrinsicInternal.h | 21 + .../BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf | 52 + .../Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm | 131 + .../Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm | 293 ++ .../Library/BaseIoLibIntrinsic/IoHighLevel.c | 2350 +++++++++++ .../edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c | 311 ++ .../Library/BaseIoLibIntrinsic/IoLibArmVirt.c | 727 ++++ .../MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c | 336 ++ .../MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c | 184 + .../Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c | 405 ++ .../MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c | 222 ++ .../MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c | 595 +++ .../Library/BaseIoLibIntrinsic/X64/IoFifo.nasm | 120 + .../Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm | 282 ++ .../MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S | 31 + .../Library/BaseLib/AArch64/CpuBreakpoint.asm | 33 + .../Library/BaseLib/AArch64/DisableInterrupts.S | 30 + .../Library/BaseLib/AArch64/DisableInterrupts.asm | 31 + .../Library/BaseLib/AArch64/EnableInterrupts.S | 30 + .../Library/BaseLib/AArch64/EnableInterrupts.asm | 31 + .../Library/BaseLib/AArch64/GetInterruptsState.S | 39 + .../Library/BaseLib/AArch64/GetInterruptsState.asm | 43 + .../MdePkg/Library/BaseLib/AArch64/MemoryFence.S | 33 + .../MdePkg/Library/BaseLib/AArch64/MemoryFence.asm | 32 + .../Library/BaseLib/AArch64/SetJumpLongJump.S | 91 + .../Library/BaseLib/AArch64/SetJumpLongJump.asm | 95 + .../Library/BaseLib/AArch64/SpeculationBarrier.S | 33 + .../Library/BaseLib/AArch64/SpeculationBarrier.asm | 32 + .../MdePkg/Library/BaseLib/AArch64/SwitchStack.S | 65 + .../MdePkg/Library/BaseLib/AArch64/SwitchStack.asm | 65 + roms/edk2/MdePkg/Library/BaseLib/ARShiftU64.c | 35 + .../MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S | 30 + .../MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm | 35 + roms/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm | 35 + .../MdePkg/Library/BaseLib/Arm/DisableInterrupts.S | 29 + .../Library/BaseLib/Arm/DisableInterrupts.asm | 31 + .../MdePkg/Library/BaseLib/Arm/EnableInterrupts.S | 30 + .../Library/BaseLib/Arm/EnableInterrupts.asm | 31 + .../Library/BaseLib/Arm/GetInterruptsState.S | 37 + .../Library/BaseLib/Arm/GetInterruptsState.asm | 39 + .../Library/BaseLib/Arm/InternalSwitchStack.c | 73 + roms/edk2/MdePkg/Library/BaseLib/Arm/Math64.S | 263 ++ roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S | 33 + .../MdePkg/Library/BaseLib/Arm/MemoryFence.asm | 33 + .../MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S | 64 + .../MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm | 64 + .../Library/BaseLib/Arm/SpeculationBarrier.S | 33 + .../Library/BaseLib/Arm/SpeculationBarrier.asm | 33 + roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S | 62 + .../MdePkg/Library/BaseLib/Arm/SwitchStack.asm | 39 + roms/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c | 246 ++ roms/edk2/MdePkg/Library/BaseLib/BaseLib.inf | 422 ++ roms/edk2/MdePkg/Library/BaseLib/BaseLib.uni | 18 + .../edk2/MdePkg/Library/BaseLib/BaseLibInternals.h | 869 ++++ roms/edk2/MdePkg/Library/BaseLib/BitField.c | 1002 +++++ roms/edk2/MdePkg/Library/BaseLib/CheckSum.c | 626 +++ roms/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c | 18 + roms/edk2/MdePkg/Library/BaseLib/Cpu.c | 59 + roms/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c | 32 + .../MdePkg/Library/BaseLib/DivS64x64Remainder.c | 47 + roms/edk2/MdePkg/Library/BaseLib/DivU64x32.c | 39 + .../MdePkg/Library/BaseLib/DivU64x32Remainder.c | 43 + .../MdePkg/Library/BaseLib/DivU64x64Remainder.c | 43 + .../MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c | 123 + .../MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c | 62 + .../Library/BaseLib/Ebc/SpeculationBarrier.c | 24 + roms/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c | 52 + roms/edk2/MdePkg/Library/BaseLib/FilePaths.c | 115 + roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c | 38 + roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c | 38 + roms/edk2/MdePkg/Library/BaseLib/HighBitSet32.c | 41 + roms/edk2/MdePkg/Library/BaseLib/HighBitSet64.c | 49 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c | 45 + .../MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm | 39 + .../MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c | 35 + .../MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm | 30 + roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c | 68 + roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm | 59 + roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c | 76 + roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm | 61 + roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c | 29 + .../edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm | 30 + .../MdePkg/Library/BaseLib/Ia32/DisableCache.c | 30 + .../MdePkg/Library/BaseLib/Ia32/DisableCache.nasm | 36 + .../Library/BaseLib/Ia32/DisableInterrupts.c | 26 + .../Library/BaseLib/Ia32/DisableInterrupts.nasm | 31 + .../MdePkg/Library/BaseLib/Ia32/DisablePaging32.c | 71 + .../Library/BaseLib/Ia32/DisablePaging32.nasm | 48 + .../Library/BaseLib/Ia32/DivS64x64Remainder.c | 47 + roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c | 44 + .../MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm | 37 + .../Library/BaseLib/Ia32/DivU64x32Remainder.c | 49 + .../Library/BaseLib/Ia32/DivU64x32Remainder.nasm | 42 + .../Library/BaseLib/Ia32/DivU64x64Remainder.nasm | 88 + .../edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c | 30 + .../MdePkg/Library/BaseLib/Ia32/EnableCache.nasm | 36 + .../Library/BaseLib/Ia32/EnableDisableInterrupts.c | 30 + .../BaseLib/Ia32/EnableDisableInterrupts.nasm | 32 + .../MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c | 26 + .../Library/BaseLib/Ia32/EnableInterrupts.nasm | 31 + .../MdePkg/Library/BaseLib/Ia32/EnablePaging32.c | 75 + .../Library/BaseLib/Ia32/EnablePaging32.nasm | 48 + .../Library/BaseLib/Ia32/EnablePaging64.nasm | 59 + .../MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c | 52 + .../Library/BaseLib/Ia32/FlushCacheLine.nasm | 45 + roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c | 34 + .../MdePkg/Library/BaseLib/Ia32/FxRestore.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c | 586 +++ .../MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c | 1170 ++++++ .../Library/BaseLib/Ia32/InternalSwitchStack.c | 54 + .../Library/BaseLib/Ia32/InternalSwitchStack.nasm | 41 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c | 29 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c | 49 + roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm | 44 + roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c | 45 + .../MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm | 39 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm | 30 + .../edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm | 60 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c | 42 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c | 41 + .../MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c | 45 + .../MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm | 40 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c | 38 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm | 34 + .../MdePkg/Library/BaseLib/Ia32/Non-existing.c | 51 + roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c | 49 + roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm | 44 + roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c | 45 + .../MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm | 39 + roms/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm | 84 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm | 38 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm | 38 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c | 33 + .../MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c | 33 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c | 36 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm | 63 + .../edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c | 37 + .../MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm | 34 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm | 257 ++ roms/edk2/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm | 38 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c | 29 + roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c | 33 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c | 33 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm | 39 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c | 33 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm | 39 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c | 33 + .../MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c | 35 + .../MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c | 33 + .../MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c | 31 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c | 32 + .../edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c | 43 + .../MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm | 30 + roms/edk2/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/LRotU32.c | 36 + roms/edk2/MdePkg/Library/BaseLib/LRotU64.c | 36 + roms/edk2/MdePkg/Library/BaseLib/LShiftU64.c | 35 + roms/edk2/MdePkg/Library/BaseLib/LinkedList.c | 599 +++ roms/edk2/MdePkg/Library/BaseLib/LongJump.c | 41 + roms/edk2/MdePkg/Library/BaseLib/LowBitSet32.c | 41 + roms/edk2/MdePkg/Library/BaseLib/LowBitSet64.c | 44 + roms/edk2/MdePkg/Library/BaseLib/Math64.c | 362 ++ roms/edk2/MdePkg/Library/BaseLib/ModU64x32.c | 39 + roms/edk2/MdePkg/Library/BaseLib/MultS64x64.c | 36 + roms/edk2/MdePkg/Library/BaseLib/MultU64x32.c | 40 + roms/edk2/MdePkg/Library/BaseLib/MultU64x64.c | 40 + roms/edk2/MdePkg/Library/BaseLib/RRotU32.c | 36 + roms/edk2/MdePkg/Library/BaseLib/RRotU64.c | 36 + roms/edk2/MdePkg/Library/BaseLib/RShiftU64.c | 35 + .../MdePkg/Library/BaseLib/RiscV64/CpuBreakpoint.c | 27 + .../edk2/MdePkg/Library/BaseLib/RiscV64/CpuPause.c | 29 + .../Library/BaseLib/RiscV64/DisableInterrupts.c | 24 + .../Library/BaseLib/RiscV64/EnableInterrupts.c | 25 + .../MdePkg/Library/BaseLib/RiscV64/FlushCache.S | 21 + .../Library/BaseLib/RiscV64/GetInterruptState.c | 35 + .../Library/BaseLib/RiscV64/InternalSwitchStack.c | 55 + .../Library/BaseLib/RiscV64/RiscVCpuBreakpoint.S | 14 + .../MdePkg/Library/BaseLib/RiscV64/RiscVCpuPause.S | 14 + .../Library/BaseLib/RiscV64/RiscVInterrupt.S | 63 + .../Library/BaseLib/RiscV64/RiscVSetJumpLongJump.S | 55 + roms/edk2/MdePkg/Library/BaseLib/SafeString.c | 3535 +++++++++++++++++ roms/edk2/MdePkg/Library/BaseLib/SetJump.c | 34 + roms/edk2/MdePkg/Library/BaseLib/String.c | 2270 +++++++++++ roms/edk2/MdePkg/Library/BaseLib/SwapBytes16.c | 33 + roms/edk2/MdePkg/Library/BaseLib/SwapBytes32.c | 39 + roms/edk2/MdePkg/Library/BaseLib/SwapBytes64.c | 33 + roms/edk2/MdePkg/Library/BaseLib/SwitchStack.c | 70 + roms/edk2/MdePkg/Library/BaseLib/Unaligned.c | 216 + roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.c | 140 + roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.h | 66 + .../MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf | 251 ++ .../MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni | 11 + .../MdePkg/Library/BaseLib/X64/CpuBreakpoint.c | 33 + .../MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm | 58 + roms/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm | 60 + roms/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm | 31 + .../MdePkg/Library/BaseLib/X64/DisableCache.nasm | 37 + .../Library/BaseLib/X64/DisableInterrupts.nasm | 32 + .../Library/BaseLib/X64/DisablePaging64.nasm | 78 + .../MdePkg/Library/BaseLib/X64/EnableCache.nasm | 37 + .../BaseLib/X64/EnableDisableInterrupts.nasm | 33 + .../Library/BaseLib/X64/EnableInterrupts.nasm | 32 + .../MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm | 33 + .../edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/GccInline.c | 562 +++ .../MdePkg/Library/BaseLib/X64/GccInlinePriv.c | 1234 ++++++ roms/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm | 77 + roms/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm | 37 + roms/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm | 35 + .../edk2/MdePkg/Library/BaseLib/X64/Non-existing.c | 147 + roms/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm | 77 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm | 36 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm | 36 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm | 32 + .../MdePkg/Library/BaseLib/X64/ReadEflags.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c | 33 + .../edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm | 34 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm | 34 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm | 34 + roms/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm | 81 + .../MdePkg/Library/BaseLib/X64/SwitchStack.nasm | 45 + roms/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm | 319 ++ roms/edk2/MdePkg/Library/BaseLib/X64/VmgExit.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm | 37 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm | 37 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm | 33 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm | 33 + .../edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm | 32 + .../edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm | 35 + .../edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm | 32 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c | 36 + .../MdePkg/Library/BaseLib/X64/WriteMsr64.nasm | 35 + roms/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm | 31 + roms/edk2/MdePkg/Library/BaseLib/X64/XGetBv.nasm | 34 + .../MdePkg/Library/BaseLib/X86DisablePaging32.c | 60 + .../MdePkg/Library/BaseLib/X86DisablePaging64.c | 57 + .../MdePkg/Library/BaseLib/X86EnablePaging32.c | 63 + .../MdePkg/Library/BaseLib/X86EnablePaging64.c | 59 + roms/edk2/MdePkg/Library/BaseLib/X86FxRestore.c | 43 + roms/edk2/MdePkg/Library/BaseLib/X86FxSave.c | 42 + .../MdePkg/Library/BaseLib/X86GetInterruptState.c | 35 + roms/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c | 26 + roms/edk2/MdePkg/Library/BaseLib/X86Msr.c | 654 +++ .../MdePkg/Library/BaseLib/X86PatchInstruction.c | 83 + roms/edk2/MdePkg/Library/BaseLib/X86RdRand.c | 73 + roms/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c | 33 + roms/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c | 33 + .../MdePkg/Library/BaseLib/X86SpeculationBarrier.c | 30 + roms/edk2/MdePkg/Library/BaseLib/X86Thunk.c | 262 ++ roms/edk2/MdePkg/Library/BaseLib/X86UnitTestHost.c | 2977 ++++++++++++++ roms/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c | 33 + roms/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c | 33 + .../MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf | 52 + .../MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni | 16 + .../Library/BaseMemoryLib/CompareMemWrapper.c | 60 + roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c | 148 + .../MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c | 57 + .../Library/BaseMemoryLib/IsZeroBufferWrapper.c | 48 + .../MdePkg/Library/BaseMemoryLib/MemLibGeneric.c | 287 ++ .../edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c | 165 + .../MdePkg/Library/BaseMemoryLib/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLib/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLib/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLib/ScanMem64Wrapper.c | 61 + .../MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c | 93 + roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c | 81 + .../MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c | 58 + .../MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c | 58 + .../MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c | 58 + .../MdePkg/Library/BaseMemoryLib/SetMemWrapper.c | 85 + .../MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c | 50 + .../Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf | 102 + .../Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni | 17 + .../Library/BaseMemoryLibMmx/CompareMemWrapper.c | 60 + .../Library/BaseMemoryLibMmx/CopyMemWrapper.c | 57 + .../Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm | 51 + .../Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm | 71 + .../BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm | 49 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm | 48 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm | 48 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm | 57 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm | 48 + .../Library/BaseMemoryLibMmx/Ia32/SetMem.nasm | 62 + .../Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm | 55 + .../Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm | 49 + .../Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm | 40 + .../Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm | 48 + .../Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c | 48 + .../MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c | 165 + .../Library/BaseMemoryLibMmx/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLibMmx/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLibMmx/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLibMmx/ScanMem64Wrapper.c | 61 + .../Library/BaseMemoryLibMmx/ScanMem8Wrapper.c | 93 + .../Library/BaseMemoryLibMmx/SetMem16Wrapper.c | 58 + .../Library/BaseMemoryLibMmx/SetMem32Wrapper.c | 58 + .../Library/BaseMemoryLibMmx/SetMem64Wrapper.c | 58 + .../Library/BaseMemoryLibMmx/SetMemWrapper.c | 85 + .../Library/BaseMemoryLibMmx/X64/CompareMem.nasm | 52 + .../Library/BaseMemoryLibMmx/X64/CopyMem.nasm | 68 + .../Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm | 49 + .../Library/BaseMemoryLibMmx/X64/ScanMem16.nasm | 49 + .../Library/BaseMemoryLibMmx/X64/ScanMem32.nasm | 49 + .../Library/BaseMemoryLibMmx/X64/ScanMem64.nasm | 49 + .../Library/BaseMemoryLibMmx/X64/ScanMem8.nasm | 49 + .../Library/BaseMemoryLibMmx/X64/SetMem.nasm | 54 + .../Library/BaseMemoryLibMmx/X64/SetMem16.nasm | 53 + .../Library/BaseMemoryLibMmx/X64/SetMem32.nasm | 47 + .../Library/BaseMemoryLibMmx/X64/SetMem64.nasm | 40 + .../Library/BaseMemoryLibMmx/X64/ZeroMem.nasm | 50 + .../Library/BaseMemoryLibMmx/ZeroMemWrapper.c | 50 + .../BaseMemoryLibOptDxe/AArch64/CompareGuid.S | 18 + .../BaseMemoryLibOptDxe/AArch64/CompareMem.S | 120 + .../Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S | 236 ++ .../Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S | 139 + .../Library/BaseMemoryLibOptDxe/AArch64/SetMem.S | 199 + .../Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S | 44 + .../BaseMemoryLibOptDxe/Arm/CompareGuid.asm | 48 + .../Library/BaseMemoryLibOptDxe/Arm/CompareMem.S | 117 + .../Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm | 118 + .../Library/BaseMemoryLibOptDxe/Arm/CopyMem.S | 170 + .../Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm | 141 + .../Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c | 159 + .../Library/BaseMemoryLibOptDxe/Arm/ScanMem.S | 122 + .../Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm | 121 + .../BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c | 136 + .../Library/BaseMemoryLibOptDxe/Arm/SetMem.S | 88 + .../Library/BaseMemoryLibOptDxe/Arm/SetMem.asm | 90 + .../BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf | 125 + .../BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni | 17 + .../BaseMemoryLibOptDxe/CompareMemWrapper.c | 60 + .../Library/BaseMemoryLibOptDxe/CopyMemWrapper.c | 57 + .../BaseMemoryLibOptDxe/Ia32/CompareMem.nasm | 51 + .../Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm | 78 + .../BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm | 49 + .../BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm | 48 + .../BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm | 48 + .../BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm | 57 + .../Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm | 48 + .../Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm | 46 + .../Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm | 38 + .../Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm | 38 + .../Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm | 42 + .../Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm | 43 + .../BaseMemoryLibOptDxe/IsZeroBufferWrapper.c | 48 + .../Library/BaseMemoryLibOptDxe/MemLibGuid.c | 165 + .../Library/BaseMemoryLibOptDxe/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c | 61 + .../Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c | 94 + .../Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c | 58 + .../Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c | 58 + .../Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c | 58 + .../Library/BaseMemoryLibOptDxe/SetMemWrapper.c | 85 + .../BaseMemoryLibOptDxe/X64/CompareMem.nasm | 52 + .../Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm | 77 + .../BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm | 49 + .../Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm | 49 + .../Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm | 49 + .../Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm | 49 + .../Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm | 49 + .../Library/BaseMemoryLibOptDxe/X64/SetMem.nasm | 56 + .../Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm | 41 + .../Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm | 41 + .../Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm | 40 + .../Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm | 44 + .../Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c | 50 + .../BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf | 103 + .../BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni | 17 + .../BaseMemoryLibOptPei/CompareMemWrapper.c | 60 + .../Library/BaseMemoryLibOptPei/CopyMemWrapper.c | 57 + .../BaseMemoryLibOptPei/Ia32/CompareMem.nasm | 51 + .../Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm | 56 + .../BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm | 49 + .../BaseMemoryLibOptPei/Ia32/ScanMem16.nasm | 48 + .../BaseMemoryLibOptPei/Ia32/ScanMem32.nasm | 48 + .../BaseMemoryLibOptPei/Ia32/ScanMem64.nasm | 57 + .../Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm | 48 + .../Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm | 46 + .../Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm | 38 + .../Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm | 38 + .../Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm | 42 + .../Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm | 43 + .../BaseMemoryLibOptPei/IsZeroBufferWrapper.c | 48 + .../Library/BaseMemoryLibOptPei/MemLibGuid.c | 165 + .../Library/BaseMemoryLibOptPei/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c | 61 + .../Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c | 93 + .../Library/BaseMemoryLibOptPei/SetMem16Wrapper.c | 58 + .../Library/BaseMemoryLibOptPei/SetMem32Wrapper.c | 58 + .../Library/BaseMemoryLibOptPei/SetMem64Wrapper.c | 58 + .../Library/BaseMemoryLibOptPei/SetMemWrapper.c | 85 + .../BaseMemoryLibOptPei/X64/CompareMem.nasm | 52 + .../Library/BaseMemoryLibOptPei/X64/CopyMem.nasm | 59 + .../BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm | 49 + .../Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm | 49 + .../Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm | 49 + .../Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm | 49 + .../Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm | 49 + .../Library/BaseMemoryLibOptPei/X64/SetMem.nasm | 41 + .../Library/BaseMemoryLibOptPei/X64/SetMem16.nasm | 40 + .../Library/BaseMemoryLibOptPei/X64/SetMem32.nasm | 40 + .../Library/BaseMemoryLibOptPei/X64/SetMem64.nasm | 39 + .../Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm | 43 + .../Library/BaseMemoryLibOptPei/ZeroMemWrapper.c | 50 + .../BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf | 100 + .../BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni | 17 + .../BaseMemoryLibRepStr/CompareMemWrapper.c | 60 + .../Library/BaseMemoryLibRepStr/CopyMemWrapper.c | 57 + .../BaseMemoryLibRepStr/Ia32/CompareMem.nasm | 51 + .../Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm | 58 + .../BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm | 49 + .../BaseMemoryLibRepStr/Ia32/ScanMem16.nasm | 50 + .../BaseMemoryLibRepStr/Ia32/ScanMem32.nasm | 50 + .../BaseMemoryLibRepStr/Ia32/ScanMem64.nasm | 59 + .../Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm | 50 + .../Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm | 38 + .../Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm | 38 + .../Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm | 38 + .../Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm | 42 + .../Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm | 43 + .../BaseMemoryLibRepStr/IsZeroBufferWrapper.c | 48 + .../Library/BaseMemoryLibRepStr/MemLibGuid.c | 165 + .../Library/BaseMemoryLibRepStr/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c | 61 + .../Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c | 93 + .../Library/BaseMemoryLibRepStr/SetMem16Wrapper.c | 58 + .../Library/BaseMemoryLibRepStr/SetMem32Wrapper.c | 58 + .../Library/BaseMemoryLibRepStr/SetMem64Wrapper.c | 58 + .../Library/BaseMemoryLibRepStr/SetMemWrapper.c | 85 + .../BaseMemoryLibRepStr/X64/CompareMem.nasm | 52 + .../Library/BaseMemoryLibRepStr/X64/CopyMem.nasm | 59 + .../BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm | 49 + .../Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm | 49 + .../Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm | 49 + .../Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm | 49 + .../Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm | 49 + .../Library/BaseMemoryLibRepStr/X64/SetMem.nasm | 40 + .../Library/BaseMemoryLibRepStr/X64/SetMem16.nasm | 40 + .../Library/BaseMemoryLibRepStr/X64/SetMem32.nasm | 40 + .../Library/BaseMemoryLibRepStr/X64/SetMem64.nasm | 39 + .../Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm | 43 + .../Library/BaseMemoryLibRepStr/ZeroMemWrapper.c | 50 + .../BaseMemoryLibSse2/BaseMemoryLibSse2.inf | 99 + .../BaseMemoryLibSse2/BaseMemoryLibSse2.uni | 16 + .../Library/BaseMemoryLibSse2/CompareMemWrapper.c | 60 + .../Library/BaseMemoryLibSse2/CopyMemWrapper.c | 57 + .../Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm | 51 + .../Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm | 78 + .../BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm | 68 + .../Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm | 48 + .../Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm | 48 + .../Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm | 57 + .../Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm | 48 + .../Library/BaseMemoryLibSse2/Ia32/SetMem.nasm | 67 + .../Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm | 63 + .../Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm | 62 + .../Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm | 54 + .../Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm | 59 + .../BaseMemoryLibSse2/IsZeroBufferWrapper.c | 48 + .../MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c | 165 + .../Library/BaseMemoryLibSse2/MemLibInternals.h | 245 ++ .../Library/BaseMemoryLibSse2/ScanMem16Wrapper.c | 61 + .../Library/BaseMemoryLibSse2/ScanMem32Wrapper.c | 60 + .../Library/BaseMemoryLibSse2/ScanMem64Wrapper.c | 61 + .../Library/BaseMemoryLibSse2/ScanMem8Wrapper.c | 93 + .../Library/BaseMemoryLibSse2/SetMem16Wrapper.c | 58 + .../Library/BaseMemoryLibSse2/SetMem32Wrapper.c | 58 + .../Library/BaseMemoryLibSse2/SetMem64Wrapper.c | 58 + .../Library/BaseMemoryLibSse2/SetMemWrapper.c | 85 + .../Library/BaseMemoryLibSse2/X64/CompareMem.nasm | 52 + .../Library/BaseMemoryLibSse2/X64/CopyMem.nasm | 77 + .../BaseMemoryLibSse2/X64/IsZeroBuffer.nasm | 70 + .../Library/BaseMemoryLibSse2/X64/ScanMem16.nasm | 49 + .../Library/BaseMemoryLibSse2/X64/ScanMem32.nasm | 49 + .../Library/BaseMemoryLibSse2/X64/ScanMem64.nasm | 49 + .../Library/BaseMemoryLibSse2/X64/ScanMem8.nasm | 49 + .../Library/BaseMemoryLibSse2/X64/SetMem.nasm | 65 + .../Library/BaseMemoryLibSse2/X64/SetMem16.nasm | 63 + .../Library/BaseMemoryLibSse2/X64/SetMem32.nasm | 62 + .../Library/BaseMemoryLibSse2/X64/SetMem64.nasm | 53 + .../Library/BaseMemoryLibSse2/X64/ZeroMem.nasm | 59 + .../Library/BaseMemoryLibSse2/ZeroMemWrapper.c | 50 + .../BaseOrderedCollectionRedBlackTreeLib.c | 1448 +++++++ .../BaseOrderedCollectionRedBlackTreeLib.inf | 44 + .../BaseOrderedCollectionRedBlackTreeLib.uni | 24 + .../Library/BasePcdLibNull/BasePcdLibNull.inf | 37 + .../Library/BasePcdLibNull/BasePcdLibNull.uni | 17 + roms/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c | 1474 +++++++ .../MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf | 37 + .../MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni | 17 + roms/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c | 1778 +++++++++ .../BasePciExpressLib/BasePciExpressLib.inf | 41 + .../BasePciExpressLib/BasePciExpressLib.uni | 17 + .../Library/BasePciExpressLib/PciExpressLib.c | 1413 +++++++ .../MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf | 35 + .../MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni | 17 + roms/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c | 1132 ++++++ .../BasePciLibPciExpress/BasePciLibPciExpress.inf | 36 + .../BasePciLibPciExpress/BasePciLibPciExpress.uni | 17 + .../MdePkg/Library/BasePciLibPciExpress/PciLib.c | 1132 ++++++ .../BasePciSegmentInfoLibNull.inf | 36 + .../BasePciSegmentInfoLibNull.uni | 15 + .../BasePciSegmentInfoLibNull/PciSegmentInfoLib.c | 32 + .../BasePciSegmentLibPci/BasePciSegmentLibPci.inf | 38 + .../BasePciSegmentLibPci/BasePciSegmentLibPci.uni | 16 + .../Library/BasePciSegmentLibPci/PciSegmentLib.c | 1283 ++++++ .../BasePeCoffExtraActionLibNull.inf | 33 + .../PeCoffExtraActionLib.c | 48 + .../PeCoffExtraActionLibNull.uni | 16 + .../BasePeCoffGetEntryPointLib.inf | 35 + .../BasePeCoffGetEntryPointLib.uni | 16 + .../PeCoffGetEntryPoint.c | 382 ++ .../Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 244 ++ .../edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 1944 +++++++++ .../MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 56 + .../MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni | 26 + .../Library/BasePeCoffLib/BasePeCoffLibInternals.h | 136 + .../MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 84 + .../Library/BasePeCoffLib/RiscV/PeCoffLoaderEx.c | 133 + .../BasePerformanceLibNull.inf | 40 + .../BasePerformanceLibNull.uni | 16 + .../BasePerformanceLibNull/PerformanceLib.c | 355 ++ .../BasePostCodeLibDebug/BasePostCodeLibDebug.inf | 45 + .../BasePostCodeLibDebug/BasePostCodeLibDebug.uni | 17 + .../MdePkg/Library/BasePostCodeLibDebug/PostCode.c | 121 + .../BasePostCodeLibPort80.inf | 43 + .../BasePostCodeLibPort80.uni | 16 + .../Library/BasePostCodeLibPort80/PostCode.c | 139 + .../MdePkg/Library/BasePrintLib/BasePrintLib.inf | 45 + .../MdePkg/Library/BasePrintLib/BasePrintLib.uni | 16 + roms/edk2/MdePkg/Library/BasePrintLib/PrintLib.c | 955 +++++ .../MdePkg/Library/BasePrintLib/PrintLibInternal.c | 1272 ++++++ .../MdePkg/Library/BasePrintLib/PrintLibInternal.h | 271 ++ .../BaseReportStatusCodeLib.c | 386 ++ .../BaseReportStatusCodeLibNull.inf | 34 + .../BaseReportStatusCodeLibNull.uni | 16 + roms/edk2/MdePkg/Library/BaseRngLib/BaseRng.c | 183 + roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf | 36 + roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni | 17 + .../MdePkg/Library/BaseRngLibNull/BaseRngLibNull.c | 94 + .../Library/BaseRngLibNull/BaseRngLibNull.inf | 30 + .../Library/BaseRngLibNull/BaseRngLibNull.uni | 14 + .../BaseS3BootScriptLibNull.inf | 37 + .../BaseS3BootScriptLibNull.uni | 18 + .../BaseS3BootScriptLibNull/BootScriptLib.c | 561 +++ .../MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf | 40 + .../MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni | 17 + roms/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c | 3305 ++++++++++++++++ .../MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf | 41 + .../MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni | 17 + roms/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c | 1262 ++++++ .../BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf | 39 + .../BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni | 17 + .../Library/BaseS3PciSegmentLib/S3PciSegmentLib.c | 1243 ++++++ .../Library/BaseS3SmbusLib/BaseS3SmbusLib.inf | 41 + .../Library/BaseS3SmbusLib/BaseS3SmbusLib.uni | 17 + .../MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c | 495 +++ .../Library/BaseS3StallLib/BaseS3StallLib.inf | 39 + .../Library/BaseS3StallLib/BaseS3StallLib.uni | 17 + .../MdePkg/Library/BaseS3StallLib/S3StallLib.c | 45 + .../Library/BaseSafeIntLib/BaseSafeIntLib.inf | 47 + .../MdePkg/Library/BaseSafeIntLib/SafeIntLib.c | 4148 ++++++++++++++++++++ .../MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c | 538 +++ .../MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c | 491 +++ .../MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c | 597 +++ .../BaseSerialPortLibNull/BaseSerialPortLibNull.c | 191 + .../BaseSerialPortLibNull.inf | 31 + .../BaseSerialPortLibNull.uni | 16 + .../Library/BaseSmbusLibNull/BaseSmbusLibNull.c | 538 +++ .../Library/BaseSmbusLibNull/BaseSmbusLibNull.inf | 30 + .../Library/BaseSmbusLibNull/BaseSmbusLibNull.uni | 16 + .../Library/BaseStackCheckLib/BaseStackCheckGcc.c | 49 + .../BaseStackCheckLib/BaseStackCheckLib.inf | 40 + .../BaseStackCheckLib/BaseStackCheckLib.uni | 16 + .../Library/BaseStackCheckLib/BaseStackCheckNull.c | 9 + .../AArch64/Synchronization.S | 199 + .../AArch64/Synchronization.asm | 199 + .../BaseSynchronizationLib/Arm/Synchronization.S | 207 + .../BaseSynchronizationLib/Arm/Synchronization.asm | 208 + .../BaseSynchronizationLib.inf | 97 + .../BaseSynchronizationLib.uni | 17 + .../BaseSynchronizationLibInternals.h | 145 + .../BaseSynchronizationLib/Ebc/Synchronization.c | 141 + .../BaseSynchronizationLib/Ia32/GccInline.c | 201 + .../Ia32/InterlockedCompareExchange16.c | 45 + .../Ia32/InterlockedCompareExchange16.nasm | 37 + .../Ia32/InterlockedCompareExchange32.c | 44 + .../Ia32/InterlockedCompareExchange32.nasm | 36 + .../Ia32/InterlockedCompareExchange64.c | 44 + .../Ia32/InterlockedCompareExchange64.nasm | 42 + .../Ia32/InterlockedDecrement.nasm | 33 + .../Ia32/InterlockedIncrement.nasm | 34 + .../Ia32/InternalGetSpinLockProperties.c | 58 + .../InterlockedDecrementMsc.c | 40 + .../InterlockedIncrementMsc.c | 40 + .../RiscV64/Synchronization.S | 78 + .../BaseSynchronizationLib/Synchronization.c | 410 ++ .../BaseSynchronizationLib/SynchronizationGcc.c | 426 ++ .../BaseSynchronizationLib/SynchronizationMsc.c | 428 ++ .../Library/BaseSynchronizationLib/X64/GccInline.c | 200 + .../X64/InterlockedCompareExchange16.c | 48 + .../X64/InterlockedCompareExchange16.nasm | 36 + .../X64/InterlockedCompareExchange32.c | 48 + .../X64/InterlockedCompareExchange32.nasm | 35 + .../X64/InterlockedCompareExchange64.c | 47 + .../X64/InterlockedCompareExchange64.nasm | 35 + .../X64/InterlockedDecrement.nasm | 33 + .../X64/InterlockedIncrement.nasm | 34 + .../BaseTimerLibNullTemplate.inf | 40 + .../BaseTimerLibNullTemplate.uni | 19 + .../BaseTimerLibNullTemplate/TimerLibNull.c | 128 + .../BaseUefiDecompressLib/BaseUefiDecompressLib.c | 863 ++++ .../BaseUefiDecompressLib.inf | 38 + .../BaseUefiDecompressLib.uni | 16 + .../BaseUefiDecompressLibInternals.h | 248 ++ .../BaseUefiTianoCustomDecompressLib.c | 213 + .../BaseUefiTianoCustomDecompressLib.inf | 42 + .../Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c | 73 + .../DxeCoreEntryPoint/DxeCoreEntryPoint.inf | 36 + .../DxeCoreEntryPoint/DxeCoreEntryPoint.uni | 16 + .../MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf | 39 + .../MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni | 17 + roms/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c | 597 +++ .../DxeExtractGuidedSectionLib.c | 449 +++ .../DxeExtractGuidedSectionLib.inf | 42 + .../DxeExtractGuidedSectionLib.uni | 16 + roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf | 43 + roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni | 17 + roms/edk2/MdePkg/Library/DxeHobLib/HobLib.c | 631 +++ roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf | 43 + roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni | 14 + roms/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c | 169 + roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c | 606 +++ roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h | 59 + .../Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h | 166 + .../Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf | 47 + .../Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni | 16 + .../MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c | 2301 +++++++++++ roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c | 863 ++++ .../Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c | 407 ++ roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c | 1620 ++++++++ roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf | 63 + roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni | 26 + .../DxeRuntimeDebugLibSerialPort/DebugLib.c | 435 ++ .../DxeRuntimeDebugLibSerialPort.inf | 47 + .../DxeRuntimeDebugLibSerialPort.uni | 16 + .../DxeRuntimePciExpressLib.inf | 49 + .../DxeRuntimePciExpressLib.uni | 21 + .../DxeRuntimePciExpressLib/PciExpressLib.c | 1653 ++++++++ roms/edk2/MdePkg/Library/DxeServicesLib/Allocate.c | 48 + .../MdePkg/Library/DxeServicesLib/DxeServicesLib.c | 1092 ++++++ .../Library/DxeServicesLib/DxeServicesLib.inf | 60 + .../Library/DxeServicesLib/DxeServicesLib.uni | 18 + .../MdePkg/Library/DxeServicesLib/X64/Allocate.c | 63 + .../DxeServicesTableLib/DxeServicesTableLib.c | 62 + .../DxeServicesTableLib/DxeServicesTableLib.inf | 44 + .../DxeServicesTableLib/DxeServicesTableLib.uni | 17 + roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c | 98 + .../MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf | 46 + .../MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni | 16 + .../MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h | 79 + roms/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c | 586 +++ .../MmServicesTableLib/MmServicesTableLib.c | 57 + .../MmServicesTableLib/MmServicesTableLib.inf | 40 + .../MmServicesTableLib/MmServicesTableLib.uni | 18 + .../PciSegmentLibSegmentInfo/BasePciSegmentLib.c | 64 + .../BasePciSegmentLibSegmentInfo.inf | 41 + .../BasePciSegmentLibSegmentInfo.uni | 16 + .../DxeRuntimePciSegmentLib.c | 313 ++ .../DxeRuntimePciSegmentLibSegmentInfo.inf | 47 + .../DxeRuntimePciSegmentLibSegmentInfo.uni | 16 + .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.c | 1368 +++++++ .../PciSegmentLibSegmentInfo/PciSegmentLibCommon.h | 51 + .../Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c | 95 + .../PeiCoreEntryPoint/PeiCoreEntryPoint.inf | 34 + .../PeiCoreEntryPoint/PeiCoreEntryPoint.uni | 16 + .../PeiDxePostCodeLibReportStatusCode.inf | 40 + .../PeiDxePostCodeLibReportStatusCode.uni | 16 + .../PeiDxePostCodeLibReportStatusCode/PostCode.c | 153 + .../PeiExtractGuidedSectionLib.c | 513 +++ .../PeiExtractGuidedSectionLib.inf | 43 + .../PeiExtractGuidedSectionLib.uni | 16 + roms/edk2/MdePkg/Library/PeiHobLib/HobLib.c | 852 ++++ roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf | 51 + roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni | 16 + .../MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c | 2350 +++++++++++ roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c | 829 ++++ .../MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c | 412 ++ .../MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf | 43 + .../MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni | 17 + .../PeiMemoryAllocationLib/MemoryAllocationLib.c | 842 ++++ .../PeiMemoryAllocationLib.inf | 40 + .../PeiMemoryAllocationLib.uni | 17 + .../Library/PeiMemoryLib/CompareMemWrapper.c | 60 + .../MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c | 57 + .../Library/PeiMemoryLib/IsZeroBufferWrapper.c | 48 + roms/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c | 65 + .../MdePkg/Library/PeiMemoryLib/MemLibGeneric.c | 283 ++ roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c | 165 + .../MdePkg/Library/PeiMemoryLib/MemLibInternals.h | 243 ++ .../MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf | 55 + .../MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni | 17 + .../MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c | 61 + .../MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c | 60 + .../MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c | 61 + .../MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c | 93 + .../MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c | 58 + .../MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c | 58 + .../MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c | 58 + .../MdePkg/Library/PeiMemoryLib/SetMemWrapper.c | 85 + .../MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c | 50 + roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c | 1619 ++++++++ roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf | 61 + roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni | 28 + roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c | 1415 +++++++ .../Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf | 51 + .../Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni | 20 + .../PeiPciSegmentLibPciCfg2/PciSegmentLib.c | 1407 +++++++ .../PeiPciSegmentLibPciCfg2.inf | 48 + .../PeiPciSegmentLibPciCfg2.uni | 19 + .../PeiResourcePublicationLib.c | 52 + .../PeiResourcePublicationLib.inf | 37 + .../PeiResourcePublicationLib.uni | 16 + .../MdePkg/Library/PeiServicesLib/PeiServicesLib.c | 809 ++++ .../Library/PeiServicesLib/PeiServicesLib.inf | 43 + .../Library/PeiServicesLib/PeiServicesLib.uni | 16 + .../PeiServicesTablePointer.c | 110 + .../PeiServicesTablePointerLib.inf | 39 + .../PeiServicesTablePointerLib.uni | 18 + .../PeiServicesTablePointer.c | 125 + .../PeiServicesTablePointerLibIdt.inf | 38 + .../PeiServicesTablePointerLibIdt.uni | 17 + .../PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h | 74 + .../Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c | 89 + .../PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf | 45 + .../PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni | 16 + .../MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c | 578 +++ .../MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c | 75 + .../Library/PeimEntryPoint/PeimEntryPoint.inf | 34 + .../Library/PeimEntryPoint/PeimEntryPoint.uni | 16 + .../SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf | 54 + .../SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni | 26 + .../Library/SecPeiDxeTimerLibCpu/X86TimerLib.c | 369 ++ .../SmiHandlerProfileLibNull.c | 72 + .../SmiHandlerProfileLibNull.inf | 31 + .../SmiHandlerProfileLibNull.uni | 16 + roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c | 325 ++ roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf | 47 + roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni | 18 + .../MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c | 2306 +++++++++++ roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c | 797 ++++ .../Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c | 411 ++ .../SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h | 112 + .../SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf | 44 + .../SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni | 17 + roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c | 97 + roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf | 32 + roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni | 16 + roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c | 652 +++ roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf | 56 + roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni | 19 + .../SmmMemoryAllocationLib/MemoryAllocationLib.c | 976 +++++ .../SmmMemoryAllocationLib.inf | 45 + .../SmmMemoryAllocationLib.uni | 17 + .../Library/SmmPciExpressLib/PciExpressLib.c | 1424 +++++++ .../Library/SmmPciExpressLib/SmmPciExpressLib.inf | 37 + .../Library/SmmPciLibPciRootBridgeIo/PciLib.c | 1427 +++++++ .../SmmPciLibPciRootBridgeIo.inf | 50 + .../SmmPciLibPciRootBridgeIo.uni | 20 + .../Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c | 1169 ++++++ .../SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf | 47 + .../SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni | 16 + .../SmmServicesTableLib/SmmServicesTableLib.c | 79 + .../SmmServicesTableLib/SmmServicesTableLib.inf | 40 + .../SmmServicesTableLib/SmmServicesTableLib.uni | 16 + .../StandaloneMmDriverEntryPoint.c | 81 + .../StandaloneMmDriverEntryPoint.inf | 38 + .../StandaloneMmDriverEntryPoint.uni | 17 + .../StandaloneMmServicesTableLib.c | 35 + .../StandaloneMmServicesTableLib.inf | 34 + .../StandaloneMmServicesTableLib.uni | 15 + .../ApplicationEntryPoint.c | 115 + .../UefiApplicationEntryPoint.inf | 35 + .../UefiApplicationEntryPoint.uni | 16 + .../UefiBootServicesTableLib.c | 60 + .../UefiBootServicesTableLib.inf | 35 + .../UefiBootServicesTableLib.uni | 16 + .../MdePkg/Library/UefiDebugLibConOut/DebugLib.c | 374 ++ .../UefiDebugLibConOut/DebugLibConstructor.c | 99 + .../UefiDebugLibConOut/UefiDebugLibConOut.inf | 53 + .../UefiDebugLibConOut/UefiDebugLibConOut.uni | 16 + .../UefiDebugLibDebugPortProtocol/DebugLib.c | 429 ++ .../DebugLibConstructor.c | 99 + .../UefiDebugLibDebugPortProtocol.inf | 56 + .../UefiDebugLibDebugPortProtocol.uni | 16 + .../MdePkg/Library/UefiDebugLibStdErr/DebugLib.c | 375 ++ .../UefiDebugLibStdErr/DebugLibConstructor.c | 99 + .../UefiDebugLibStdErr/UefiDebugLibStdErr.inf | 51 + .../UefiDebugLibStdErr/UefiDebugLibStdErr.uni | 16 + .../Library/UefiDevicePathLib/DevicePathFromText.c | 3666 +++++++++++++++++ .../Library/UefiDevicePathLib/DevicePathToText.c | 2455 ++++++++++++ .../UefiDevicePathLib/DevicePathUtilities.c | 897 +++++ .../Library/UefiDevicePathLib/UefiDevicePathLib.c | 354 ++ .../Library/UefiDevicePathLib/UefiDevicePathLib.h | 451 +++ .../UefiDevicePathLib/UefiDevicePathLib.inf | 74 + .../UefiDevicePathLib/UefiDevicePathLib.uni | 16 + .../UefiDevicePathLibOptionalDevicePathProtocol.c | 478 +++ ...UefiDevicePathLibOptionalDevicePathProtocol.inf | 84 + ...UefiDevicePathLibOptionalDevicePathProtocol.uni | 18 + .../UefiDevicePathLib.c | 865 ++++ .../UefiDevicePathLibDevicePathProtocol.inf | 56 + .../UefiDevicePathLibDevicePathProtocol.uni | 17 + .../UefiDriverEntryPoint/DriverEntryPoint.c | 167 + .../UefiDriverEntryPoint/UefiDriverEntryPoint.inf | 62 + .../UefiDriverEntryPoint/UefiDriverEntryPoint.uni | 16 + .../Library/UefiFileHandleLib/UefiFileHandleLib.c | 1281 ++++++ .../UefiFileHandleLib/UefiFileHandleLib.inf | 42 + .../UefiFileHandleLib/UefiFileHandleLib.uni | 20 + roms/edk2/MdePkg/Library/UefiLib/Acpi.c | 422 ++ roms/edk2/MdePkg/Library/UefiLib/Console.c | 566 +++ roms/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c | 2020 ++++++++++ roms/edk2/MdePkg/Library/UefiLib/UefiLib.c | 2013 ++++++++++ roms/edk2/MdePkg/Library/UefiLib/UefiLib.inf | 88 + roms/edk2/MdePkg/Library/UefiLib/UefiLib.uni | 20 + roms/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h | 39 + roms/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c | 816 ++++ roms/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c | 330 ++ .../UefiMemoryAllocationLib/MemoryAllocationLib.c | 815 ++++ .../UefiMemoryAllocationLib.inf | 37 + .../UefiMemoryAllocationLib.uni | 17 + .../Library/UefiMemoryLib/CompareMemWrapper.c | 60 + .../MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c | 57 + .../Library/UefiMemoryLib/IsZeroBufferWrapper.c | 48 + roms/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c | 57 + .../MdePkg/Library/UefiMemoryLib/MemLibGeneric.c | 283 ++ .../edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c | 165 + .../MdePkg/Library/UefiMemoryLib/MemLibInternals.h | 243 ++ .../Library/UefiMemoryLib/ScanMem16Wrapper.c | 61 + .../Library/UefiMemoryLib/ScanMem32Wrapper.c | 60 + .../Library/UefiMemoryLib/ScanMem64Wrapper.c | 61 + .../MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c | 93 + .../MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c | 58 + .../MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c | 58 + .../MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c | 58 + .../MdePkg/Library/UefiMemoryLib/SetMemWrapper.c | 85 + .../MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf | 55 + .../MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni | 17 + .../MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c | 50 + .../Library/UefiPciLibPciRootBridgeIo/PciLib.c | 1427 +++++++ .../UefiPciLibPciRootBridgeIo.inf | 52 + .../UefiPciLibPciRootBridgeIo.uni | 20 + .../PciSegmentLib.c | 1484 +++++++ .../PciSegmentLib.h | 51 + .../UefiPciSegmentLibPciRootBridgeIo.inf | 55 + .../UefiPciSegmentLibPciRootBridgeIo.uni | 20 + .../MdePkg/Library/UefiRuntimeLib/RuntimeLib.c | 835 ++++ .../Library/UefiRuntimeLib/UefiRuntimeLib.inf | 41 + .../Library/UefiRuntimeLib/UefiRuntimeLib.uni | 18 + .../UefiRuntimeServicesTableLib.c | 43 + .../UefiRuntimeServicesTableLib.inf | 36 + .../UefiRuntimeServicesTableLib.uni | 16 + roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c | 2290 +++++++++++ .../MdePkg/Library/UefiScsiLib/UefiScsiLib.inf | 42 + .../MdePkg/Library/UefiScsiLib/UefiScsiLib.uni | 17 + roms/edk2/MdePkg/Library/UefiUsbLib/Hid.c | 482 +++ roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf | 43 + roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni | 17 + .../MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h | 24 + roms/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c | 665 ++++ 1083 files changed, 166579 insertions(+) create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/RiscVCache.c create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/RiscV/Cpu.S create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni create mode 100644 roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/ARShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c create mode 100755 roms/edk2/MdePkg/Library/BaseLib/Arm/Math64.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/BaseLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseLib/BaseLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseLib/BitField.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/CheckSum.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Cpu.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/DivU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/FilePaths.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/HighBitSet32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/HighBitSet64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LRotU32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LRotU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LinkedList.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LongJump.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LowBitSet32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/LowBitSet64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Math64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/ModU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/MultS64x64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/MultU64x32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/MultU64x64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RRotU32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RRotU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RShiftU64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuBreakpoint.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuPause.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/DisableInterrupts.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/EnableInterrupts.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/FlushCache.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/GetInterruptState.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/InternalSwitchStack.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuBreakpoint.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuPause.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVSetJumpLongJump.S create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SafeString.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SetJump.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/String.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SwapBytes16.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SwapBytes32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SwapBytes64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/SwitchStack.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/Unaligned.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.h create mode 100644 roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/GccInline.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/GccInlinePriv.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/VmgExit.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X64/XGetBv.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86FxRestore.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86FxSave.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86Msr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86RdRand.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86Thunk.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86UnitTestHost.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni create mode 100644 roms/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c create mode 100644 roms/edk2/MdePkg/Library/BasePeCoffLib/RiscV/PeCoffLoaderEx.c create mode 100644 roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni create mode 100644 roms/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c create mode 100644 roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf create mode 100644 roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni create mode 100644 roms/edk2/MdePkg/Library/BasePrintLib/PrintLib.c create mode 100644 roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c create mode 100644 roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h create mode 100644 roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseRngLib/BaseRng.c create mode 100644 roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c create mode 100644 roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c create mode 100644 roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c create mode 100644 roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm create mode 100755 roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/RiscV64/Synchronization.S create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm create mode 100644 roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf create mode 100644 roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni create mode 100644 roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.c create mode 100644 roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeHobLib/HobLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c create mode 100644 roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c create mode 100644 roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c create mode 100644 roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c create mode 100644 roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeServicesLib/Allocate.c create mode 100644 roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c create mode 100644 roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c create mode 100644 roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf create mode 100644 roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni create mode 100644 roms/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h create mode 100644 roms/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c create mode 100644 roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c create mode 100644 roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h create mode 100644 roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf create mode 100644 roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni create mode 100644 roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c create mode 100644 roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiHobLib/HobLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c create mode 100644 roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c create mode 100644 roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf create mode 100644 roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf create mode 100644 roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni create mode 100644 roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf create mode 100644 roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni create mode 100644 roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf create mode 100644 roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni create mode 100644 roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h create mode 100644 roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c create mode 100644 roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf create mode 100644 roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni create mode 100644 roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c create mode 100644 roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf create mode 100644 roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni create mode 100644 roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c create mode 100644 roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c create mode 100644 roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf create mode 100644 roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni create mode 100644 roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c create mode 100644 roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf create mode 100644 roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni create mode 100644 roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni create mode 100644 roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni create mode 100644 roms/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf create mode 100644 roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni create mode 100644 roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni create mode 100644 roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLibConstructor.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLibConstructor.c create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni create mode 100644 roms/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c create mode 100644 roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf create mode 100644 roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni create mode 100644 roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiLib/Acpi.c create mode 100644 roms/edk2/MdePkg/Library/UefiLib/Console.c create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c create mode 100644 roms/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c create mode 100644 roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf create mode 100644 roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni create mode 100644 roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h create mode 100644 roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf create mode 100644 roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c create mode 100644 roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiUsbLib/Hid.c create mode 100644 roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf create mode 100644 roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni create mode 100644 roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h create mode 100644 roms/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c (limited to 'roms/edk2/MdePkg/Library') diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c new file mode 100644 index 000000000..fd324c609 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c @@ -0,0 +1,241 @@ +/** @file + Cache Maintenance Functions. These functions vary by ARM architecture so the MdePkg + versions are null functions used to make sure things will compile. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// Include common header file for this module. +// +#include +#include + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + ASSERT(FALSE); +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + ASSERT(FALSE); + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes Back and Invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + ASSERT(FALSE); +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes back and invalidates the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + ASSERT(FALSE); + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + ASSERT(FALSE); +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + ASSERT(FALSE); + return Address; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + ASSERT(FALSE); +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + ASSERT(FALSE); + return Address; +} diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf new file mode 100644 index 000000000..33114243d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf @@ -0,0 +1,54 @@ +## @file +# Instance of Cache Maintenance Library using Base Library services. +# +# Cache Maintenance Library that uses Base Library services to maintain caches. +# This library assumes there are no chipset dependencies required to maintain caches. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCacheMaintenanceLib + MODULE_UNI_FILE = BaseCacheMaintenanceLib.uni + FILE_GUID = 123dd843-57c9-4158-8418-ce68b3944ce7 + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = CacheMaintenanceLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# + +[Sources.IA32] + X86Cache.c + +[Sources.X64] + X86Cache.c + +[Sources.EBC] + EbcCache.c + +[Sources.ARM] + ArmCache.c + +[Sources.AARCH64] + ArmCache.c + +[Sources.RISCV64] + RiscVCache.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni new file mode 100644 index 000000000..2ffc0bd63 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni @@ -0,0 +1,18 @@ +// /** @file +// Instance of Cache Maintenance Library using Base Library services. +// +// Cache Maintenance Library that uses Base Library services to maintain caches. +// This library assumes there are no chipset dependencies required to maintain caches. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Cache Maintenance Library using Base Library services" + +#string STR_MODULE_DESCRIPTION #language en-US "The Cache Maintenance Library that uses Base Library services to maintain caches. This library assumes there are no chipset dependencies required to maintain caches." + diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c new file mode 100644 index 000000000..f4b9d9d90 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c @@ -0,0 +1,225 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/RiscVCache.c b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/RiscVCache.c new file mode 100644 index 000000000..21a695c84 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/RiscVCache.c @@ -0,0 +1,250 @@ +/** @file + RISC-V specific functionality for cache. + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +/** + RISC-V invalidate instruction cache. + +**/ +VOID +EFIAPI +RiscVInvalidateInstCacheAsm ( + VOID + ); + +/** + RISC-V invalidate data cache. + +**/ +VOID +EFIAPI +RiscVInvalidateDataCacheAsm ( + VOID + ); + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + RiscVInvalidateInstCacheAsm (); +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes back and invalidates the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); + return Address; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + RiscVInvalidateDataCacheAsm (); +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + DEBUG((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __FUNCTION__)); + return Address; +} diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c new file mode 100644 index 000000000..7a6a617aa --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c @@ -0,0 +1,272 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include +#include +#include + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + if (Length == 0) { + return Address; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Address)); + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + AsmWbinvd (); +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes back and invalidates the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + UINT32 RegEbx; + UINT32 RegEdx; + UINTN CacheLineSize; + UINTN Start; + UINTN End; + + if (Length == 0) { + return Address; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Address)); + + // + // If the CPU does not support CLFLUSH instruction, + // then promote flush range to flush entire cache. + // + AsmCpuid (0x01, NULL, &RegEbx, NULL, &RegEdx); + if ((RegEdx & BIT19) == 0) { + AsmWbinvd (); + return Address; + } + + // + // Cache line size is 8 * Bits 15-08 of EBX returned from CPUID 01H + // + CacheLineSize = (RegEbx & 0xff00) >> 5; + + Start = (UINTN)Address; + // + // Calculate the cache line alignment + // + End = (Start + Length + (CacheLineSize - 1)) & ~(CacheLineSize - 1); + Start &= ~((UINTN)CacheLineSize - 1); + + do { + Start = (UINTN)AsmFlushCacheLine ((VOID*)Start) + CacheLineSize; + } while (Start != End); + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + WriteBackInvalidateDataCache (); +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return WriteBackInvalidateDataCacheRange (Address, Length); +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + AsmInvd (); +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + // + // Invalidation of a data cache range without writing back is not supported on + // x86 architecture, so write back and invalidate operation is performed. + // + return WriteBackInvalidateDataCacheRange (Address, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c new file mode 100644 index 000000000..fd5b9d471 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c @@ -0,0 +1,225 @@ +/** @file + Null Cache Maintenance Librfary implementation. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes Back and Invalidate the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1); + return Address; +} diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf new file mode 100644 index 000000000..8d6eaaeaa --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf @@ -0,0 +1,29 @@ +## @file +# Null Cache Maintenance Library implementation. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCacheMaintenanceLibNull + MODULE_UNI_FILE = BaseCacheMaintenanceLibNull.uni + FILE_GUID = 13F13249-AC31-4373-8B2B-AFC5755A6FCD + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = CacheMaintenanceLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# + +[Sources] + BaseCacheMaintenanceLibNull.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib diff --git a/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni new file mode 100644 index 000000000..260c75619 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni @@ -0,0 +1,12 @@ +// /** @file +// Null Cache Maintenance Library implementation. +// +// Copyright (c) 2020, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Null instance of Cache Maintenance Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Null instance of the Cache Maintenance Library." + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S new file mode 100644 index 000000000..82a723226 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S @@ -0,0 +1,32 @@ +#------------------------------------------------------------------------------ +# +# CpuFlushTlb() for ARM +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(CpuFlushTlb) + +#/** +# Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +# +# Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +# +#**/ +#VOID +#EFIAPI +#CpuFlushTlb ( +# VOID +# )# +# +ASM_PFX(CpuFlushTlb): + tlbi vmalle1 // Invalidate Inst TLB and Data TLB + dsb sy + isb + ret diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm new file mode 100644 index 000000000..a72c9aef1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; CpuFlushTlb() for ARM +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuFlushTlb + AREA BaseCpuLib_LowLevel, CODE, READONLY + +;/** +; Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +; +; Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +; +;**/ +;VOID +;EFIAPI +;CpuFlushTlb ( +; VOID +; ); +; +CpuFlushTlb + tlbi vmalle1 // Invalidate Inst TLB and Data TLB + dsb sy + isb + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S new file mode 100644 index 000000000..410a27156 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# +# CpuSleep() for AArch64 +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM LTD. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.align 3 +GCC_ASM_EXPORT(CpuSleep) + +#/** +# Places the CPU in a sleep state until an interrupt is received. +# +# Places the CPU in a sleep state until an interrupt is received. If interrupts +# are disabled prior to calling this function, then the CPU will be placed in a +# sleep state indefinitely. +# +#**/ +#VOID +#EFIAPI +#CpuSleep ( +# VOID +# ); +# + +ASM_PFX(CpuSleep): + wfi + ret diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm new file mode 100644 index 000000000..c6e4d7e65 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; CpuSleep() for AArch64 +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM LTD. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuSleep + AREA BaseCpuLib_LowLevel, CODE, READONLY + +;/** +; Places the CPU in a sleep state until an interrupt is received. +; +; Places the CPU in a sleep state until an interrupt is received. If interrupts +; are disabled prior to calling this function, then the CPU will be placed in a +; sleep state indefinitely. +; +;**/ +;VOID +;EFIAPI +;CpuSleep ( +; VOID +; ); +; + +CpuSleep + wfi + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S new file mode 100644 index 000000000..3bafce6f3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# CpuFlushTlb() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(CpuFlushTlb) + +#/** +# Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +# +# Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +# +#**/ +#VOID +#EFIAPI +#CpuFlushTlb ( +# VOID +# )# +# +ASM_PFX(CpuFlushTlb): + mov r0,#0 + mcr p15,0,r0,c8,c5,0 // Invalidate all the unlocked entried in TLB + bx LR diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm new file mode 100644 index 000000000..1f77fc7d5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; CpuFlushTlb() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuFlushTlb + AREA cpu_flush_tlb, CODE, READONLY + +;/** +; Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +; +; Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. +; +;**/ +;VOID +;EFIAPI +;CpuFlushTlb ( +; VOID +; ); +; +CpuFlushTlb + MOV r0,#0 + MCR p15,0,r0,c8,c5,0 ;Invalidate all the unlocked entried in TLB + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S new file mode 100644 index 000000000..e2b734900 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------ +# +# CpuSleep() for ARMv7 +# +# ARMv6 versions was: +# MOV r0,#0 +# MCR p15,0,r0,c7,c0,4 ;Wait for Interrupt instruction +# +# But this is a no-op on ARMv7 +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(CpuSleep) + +#/** +# Places the CPU in a sleep state until an interrupt is received. +# +# Places the CPU in a sleep state until an interrupt is received. If interrupts +# are disabled prior to calling this function, then the CPU will be placed in a +# sleep state indefinitely. +# +#**/ +#VOID +#EFIAPI +#CpuSleep ( +# VOID +# ); +# +ASM_PFX(CpuSleep): + wfi + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm new file mode 100644 index 000000000..ae32705a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; CpuSleep() for ARMv7 +; +; ARMv6 versions was: +; MOV r0,#0 +; MCR p15,0,r0,c7,c0,4 ;Wait for Interrupt instruction +; +; But this is a no-op on ARMv7 +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuSleep + AREA cpu_sleep, CODE, READONLY + +;/** +; Places the CPU in a sleep state until an interrupt is received. +; +; Places the CPU in a sleep state until an interrupt is received. If interrupts +; are disabled prior to calling this function, then the CPU will be placed in a +; sleep state indefinitely. +; +;**/ +;VOID +;EFIAPI +;CpuSleep ( +; VOID +; ); +; +CpuSleep + WFI + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf b/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf new file mode 100644 index 000000000..950f5229b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf @@ -0,0 +1,69 @@ +## @file +# Instance of CPU Library for various architecture. +# +# CPU Library implemented using ASM functions for IA32, X64, ARM, AARCH64, +# PAL CALLs for IPF, and empty functions for EBC. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCpuLib + MODULE_UNI_FILE = BaseCpuLib.uni + FILE_GUID = 4FBD2538-249C-4b50-8F4A-A9E66609CBF6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpuLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources.IA32] + Ia32/CpuSleep.c | MSFT + Ia32/CpuFlushTlb.c | MSFT + + Ia32/CpuSleep.nasm| INTEL + Ia32/CpuFlushTlb.nasm| INTEL + + Ia32/CpuSleepGcc.c | GCC + Ia32/CpuFlushTlbGcc.c | GCC + +[Sources.X64] + X64/CpuFlushTlb.nasm + X64/CpuSleep.nasm + + +[Sources.EBC] + Ebc/CpuSleepFlushTlb.c + +[Sources.ARM] + Arm/CpuFlushTlb.asm | RVCT + Arm/CpuSleep.asm | RVCT + Arm/CpuFlushTlb.asm | MSFT + Arm/CpuSleep.asm | MSFT + Arm/CpuFlushTlb.S | GCC + Arm/CpuSleep.S | GCC + +[Sources.AARCH64] + AArch64/CpuFlushTlb.S | GCC + AArch64/CpuSleep.S | GCC + AArch64/CpuFlushTlb.asm | MSFT + AArch64/CpuSleep.asm | MSFT + +[Sources.RISCV64] + RiscV/Cpu.S + +[Packages] + MdePkg/MdePkg.dec + + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni b/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni new file mode 100644 index 000000000..80dc49578 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni @@ -0,0 +1,20 @@ +// /** @file +// Instance of CPU Library for various architecture. +// +// CPU Library implemented using ASM functions for IA-32, X64 and RISCV64, +// PAL CALLs for IPF, and empty functions for EBC. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of CPU Library for various architectures" + +#string STR_MODULE_DESCRIPTION #language en-US "CPU Library implemented using ASM functions for IA-32, X64 and RISCV64, PAL CALLs for IPF, and empty functions for EBC." + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c b/roms/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c new file mode 100644 index 000000000..77e0ef605 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c @@ -0,0 +1,40 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ) +{ +} diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c new file mode 100644 index 000000000..89341c2f0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c @@ -0,0 +1,28 @@ +/** @file + CpuFlushTlb function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ) +{ + _asm { + mov eax, cr3 + mov cr3, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm new file mode 100644 index 000000000..bc3b68e3f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuFlushTlb.Asm +; +; Abstract: +; +; CpuFlushTlb function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuFlushTlb ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuFlushTlb) +ASM_PFX(CpuFlushTlb): + mov eax, cr3 + mov cr3, eax ; moving to CR3 flushes TLB + ret + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c new file mode 100644 index 000000000..15d414992 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c @@ -0,0 +1,26 @@ +/** @file + CpuFlushTlb function for Ia32/X64 GCC. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ) +{ + AsmWriteCr3 (AsmReadCr3 ()); +} + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c new file mode 100644 index 000000000..0fcaf224e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c @@ -0,0 +1,28 @@ +/** @file + CpuSleep function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ) +{ + _asm { + hlt + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm new file mode 100644 index 000000000..5e7f9abe6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm @@ -0,0 +1,30 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuSleep.Asm +; +; Abstract: +; +; CpuSleep function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuSleep ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuSleep) +ASM_PFX(CpuSleep): + hlt + ret + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c new file mode 100644 index 000000000..ad5b150d6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c @@ -0,0 +1,27 @@ +/** @file + CpuSleep function for Ia32/X64 GCC. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ) +{ + __asm__ __volatile__ ("hlt"::: "memory"); +} + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/RiscV/Cpu.S b/roms/edk2/MdePkg/Library/BaseCpuLib/RiscV/Cpu.S new file mode 100644 index 000000000..375b91d31 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/RiscV/Cpu.S @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// CpuSleep for RISC-V +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ +.data +.align 3 +.section .text + +.global ASM_PFX(_CpuSleep) + +ASM_PFX(_CpuSleep): + wfi + ret + + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm b/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm new file mode 100644 index 000000000..8ddf7a286 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuFlushTlb.Asm +; +; Abstract: +; +; CpuFlushTlb function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuFlushTlb ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuFlushTlb) +ASM_PFX(CpuFlushTlb): + mov rax, cr3 + mov cr3, rax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm b/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm new file mode 100644 index 000000000..6a0ddaf2b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuSleep.Asm +; +; Abstract: +; +; CpuSleep function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuSleep ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuSleep) +ASM_PFX(CpuSleep): + hlt + ret + diff --git a/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c new file mode 100644 index 000000000..3ba7a3509 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c @@ -0,0 +1,37 @@ +/** @file + Null instance of CPU Library. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ) +{ +} + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ) +{ +} diff --git a/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf new file mode 100644 index 000000000..a9e839903 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf @@ -0,0 +1,26 @@ +## @file +# Null instance of CPU Library. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCpuLibNull + MODULE_UNI_FILE = BaseCpuLibNull.uni + FILE_GUID = 8A29AAA5-0FB7-44CC-8709-1344FE89B878 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpuLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources] + BaseCpuLibNull.c + +[Packages] + MdePkg/MdePkg.dec diff --git a/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni new file mode 100644 index 000000000..1030221d5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni @@ -0,0 +1,11 @@ +// /** @file +// Null instance of CPU Library. +// +// Copyright (c) 2020, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Null Instance of CPU Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Null instance of CPU Library." diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf b/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf new file mode 100644 index 000000000..81a63a507 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf @@ -0,0 +1,31 @@ +## @file +# Debug Library with empty functions. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseDebugLibNull + MODULE_UNI_FILE = BaseDebugLibNull.uni + FILE_GUID = 9ba1d976-0624-41a3-8650-28165e8d9ae8 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DebugLib.c + + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni b/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni new file mode 100644 index 000000000..6d1f268d4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Debug Library with empty functions. +// +// Debug Library with empty functions. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Debug Library with empty functions" + +#string STR_MODULE_DESCRIPTION #language en-US "Debug Library with empty functions." + diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c b/roms/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c new file mode 100644 index 000000000..20c175ec6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c @@ -0,0 +1,246 @@ +/** @file + Null Base Debug Library instance with empty functions. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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(). + + @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, + ... + ) +{ +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ +} + + +/** + 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 The pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ +} + + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return Buffer; +} + + +/** + 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 FALSE; +} + + +/** + 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 FALSE; +} + + +/** + 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 FALSE; +} + + +/** + 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 FALSE; +} + +/** + 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 FALSE; +} + diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf new file mode 100644 index 000000000..7504faee6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf @@ -0,0 +1,44 @@ +## @file +# Instance of Debug Library based on Serial Port Library. +# It uses Print Library to produce formatted output strings to seiral port device. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseDebugLibSerialPort + MODULE_UNI_FILE = BaseDebugLibSerialPort.uni + FILE_GUID = BB83F95F-EDBC-4884-A520-CD42AF388FAE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib + CONSTRUCTOR = BaseDebugLibSerialPortConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DebugLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + SerialPortLib + BaseMemoryLib + PcdLib + PrintLib + BaseLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni new file mode 100644 index 000000000..ed10339f3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Debug Library based on Serial Port Library. +// +// It uses Print Library to produce formatted output strings to seiral port device. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Debug Library based on Serial Port Library" + +#string STR_MODULE_DESCRIPTION #language en-US "It uses Print Library to produce formatted output strings to a serial port device." + diff --git a/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c new file mode 100644 index 000000000..aeeab8573 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c @@ -0,0 +1,374 @@ +/** @file + Base Debug library instance base on Serial Port library. + It uses PrintLib to send debug messages to serial port device. + + NOTE: If the Serial Port library enables hardware flow control, then a call + to DebugPrint() or DebugAssert() may hang if writes to the serial port are + being blocked. This may occur if a key(s) are pressed in a terminal emulator + used to monitor the DEBUG() and ASSERT() messages. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +// +// VA_LIST can not initialize to NULL for all compiler, so we use this to +// indicate a null VA_LIST +// +VA_LIST mVaListNull; + +/** + The constructor function initialize the Serial Port Library + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +BaseDebugLibSerialPortConstructor ( + VOID + ) +{ + return SerialPortInitialize (); +} + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format 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, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled base on Null-terminated format string and a + VA_LIST argument list or a BASE_LIST argument list. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +DebugPrintMarker ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, + IN BASE_LIST BaseListMarker + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to an ASCII String + // + if (BaseListMarker == NULL) { + AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker); + } else { + AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker); + } + + // + // Send the print string to a Serial Port + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker); +} + + +/** + 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 The pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Ascii format + // + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", gEfiCallerBaseName, FileName, LineNumber, Description); + + // + // Send the print string to the Console Output device + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); + + // + // 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 The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + 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/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c new file mode 100644 index 000000000..5a43135d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c @@ -0,0 +1,53 @@ +/** @file + Debug Print Error Level library instance that retrieves the current error + level from PcdDebugPrintErrorLevel. This generic library instance does not + support the setting of the global debug print error level mask for the platform. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the debug print error level mask for the current module. + + @return Debug print error level mask for the current module. + +**/ +UINT32 +EFIAPI +GetDebugPrintErrorLevel ( + VOID + ) +{ + // + // Retrieve the current debug print error level mask from PcdDebugPrintErrorLevel. + // + return PcdGet32 (PcdDebugPrintErrorLevel); +} + +/** + Sets the global debug print error level mask fpr the entire platform. + + @param ErrorLevel Global debug print error level. + + @retval TRUE The debug print error level mask was sucessfully set. + @retval FALSE The debug print error level mask could not be set. + +**/ +BOOLEAN +EFIAPI +SetDebugPrintErrorLevel ( + UINT32 ErrorLevel + ) +{ + // + // This library uinstance does not support setting the global debug print error + // level mask. + // + return FALSE; +} diff --git a/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf new file mode 100644 index 000000000..53f7d40f3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf @@ -0,0 +1,35 @@ +## @file +# Debug Print Error Level library instance based on PcdDebugPrintErrorLevel. +# It retrieves the current error level from PcdDebugPrintErrorLevel. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseDebugPrintErrorLevelLib + MODULE_UNI_FILE = BaseDebugPrintErrorLevelLib.uni + FILE_GUID = A2C09E18-E4D2-407e-AFCC-628B79113F72 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugPrintErrorLevelLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseDebugPrintErrorLevelLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni new file mode 100644 index 000000000..ca1d00220 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Debug Print Error Level library instance based on PcdDebugPrintErrorLevel. +// +// It retrieves the current error level from PcdDebugPrintErrorLevel. +// +// Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Debug Print Error Level library instance based on PcdDebugPrintErrorLevel" + +#string STR_MODULE_DESCRIPTION #language en-US "It retrieves the current error level from PcdDebugPrintErrorLevel." + diff --git a/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c new file mode 100644 index 000000000..4d5c23c1d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c @@ -0,0 +1,478 @@ +/** @file + Provide generic extract guided section functions. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +#define EXTRACT_HANDLER_INFO_SIGNATURE SIGNATURE_32 ('E', 'G', 'S', 'I') + +typedef struct { + UINT32 Signature; + UINT32 NumberOfExtractHandler; + GUID *ExtractHandlerGuidTable; + EXTRACT_GUIDED_SECTION_DECODE_HANDLER *ExtractDecodeHandlerTable; + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable; +} EXTRACT_GUIDED_SECTION_HANDLER_INFO; + +/** + HandlerInfo table address is set by PcdGuidedExtractHandlerTableAddress, which is used to store + the registered guid and Handler list. When it is initialized, it will be directly returned. + Or, HandlerInfo table will be initialized in this function. + + @param[in, out] InfoPointer The pointer to the handler information structure. + + @retval RETURN_SUCCESS HandlerInfo table can be used to store guid and function tables. + @retval RETURN_OUT_OF_RESOURCES HandlerInfo table address is not writable. +**/ +RETURN_STATUS +GetExtractGuidedSectionHandlerInfo ( + IN OUT EXTRACT_GUIDED_SECTION_HANDLER_INFO **InfoPointer + ) +{ + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + // + // Set the available memory address to handler info. + // + HandlerInfo = (EXTRACT_GUIDED_SECTION_HANDLER_INFO*)(VOID*)(UINTN) PcdGet64 (PcdGuidedExtractHandlerTableAddress); + if (HandlerInfo == NULL) { + *InfoPointer = NULL; + return EFI_OUT_OF_RESOURCES; + } + + // + // First check whether the handler information structure is initialized. + // + if (HandlerInfo->Signature == EXTRACT_HANDLER_INFO_SIGNATURE) { + // + // The handler information has been initialized and is returned. + // + *InfoPointer = HandlerInfo; + return RETURN_SUCCESS; + } + + // + // Try to initialize the handler information structure + // + HandlerInfo->Signature = EXTRACT_HANDLER_INFO_SIGNATURE; + if (HandlerInfo->Signature != EXTRACT_HANDLER_INFO_SIGNATURE) { + // + // The handler information structure was not writeable because the memory is not ready. + // + *InfoPointer = NULL; + return RETURN_OUT_OF_RESOURCES; + } + + // + // Init HandlerInfo structure + // + HandlerInfo->NumberOfExtractHandler = 0; + HandlerInfo->ExtractHandlerGuidTable = (GUID *) (HandlerInfo + 1); + HandlerInfo->ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractHandlerGuidTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID) + ); + HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * + sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + ); + *InfoPointer = HandlerInfo; + return RETURN_SUCCESS; +} + +/** + Retrieve the list GUIDs that have been registered through ExtractGuidedSectionRegisterHandlers(). + + Sets ExtractHandlerGuidTable so it points at a callee allocated array of registered GUIDs. + The total number of GUIDs in the array are returned. Since the array of GUIDs is callee allocated + and caller must treat this array of GUIDs as read-only data. + If ExtractHandlerGuidTable is NULL, then ASSERT(). + + @param[out] ExtractHandlerGuidTable A pointer to the array of GUIDs that have been registered through + ExtractGuidedSectionRegisterHandlers(). + + @return The number of the supported extract guided Handler. + +**/ +UINTN +EFIAPI +ExtractGuidedSectionGetGuidList ( + OUT GUID **ExtractHandlerGuidTable + ) +{ + RETURN_STATUS Status; + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + ASSERT (ExtractHandlerGuidTable != NULL); + + // + // Get all registered handler information + // + Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (RETURN_ERROR (Status)) { + *ExtractHandlerGuidTable = NULL; + return 0; + } + + // + // Get GuidTable and Table Number + // + ASSERT (HandlerInfo != NULL); + *ExtractHandlerGuidTable = HandlerInfo->ExtractHandlerGuidTable; + return HandlerInfo->NumberOfExtractHandler; +} + +/** + Registers handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and EXTRACT_GUIDED_SECTION_DECODE_HANDLER + for a specific GUID section type. + + Registers the handlers specified by GetInfoHandler and DecodeHandler with the GUID specified by SectionGuid. + If the GUID value specified by SectionGuid has already been registered, then return RETURN_ALREADY_STARTED. + If there are not enough resources available to register the handlers then RETURN_OUT_OF_RESOURCES is returned. + + If SectionGuid is NULL, then ASSERT(). + If GetInfoHandler is NULL, then ASSERT(). + If DecodeHandler is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the the handlers + of the GUIDed section type being registered. + @param[in] GetInfoHandler The pointer to a function that 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. + @param[in] DecodeHandler The pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to register the handlers. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionRegisterHandlers ( + IN CONST GUID *SectionGuid, + IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler, + IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler + ) +{ + UINT32 Index; + RETURN_STATUS Status; + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + // + // Check input parameter + // + ASSERT (SectionGuid != NULL); + ASSERT (GetInfoHandler != NULL); + ASSERT (DecodeHandler != NULL); + + // + // Get the registered handler information + // + Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) { + // + // If the guided handler has been registered before, only update its handler. + // + HandlerInfo->ExtractDecodeHandlerTable [Index] = DecodeHandler; + HandlerInfo->ExtractGetInfoHandlerTable [Index] = GetInfoHandler; + return RETURN_SUCCESS; + } + } + + // + // Check the global table is enough to contain new Handler. + // + if (HandlerInfo->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) { + return RETURN_OUT_OF_RESOURCES; + } + + // + // Register new Handler and guid value. + // + CopyGuid (HandlerInfo->ExtractHandlerGuidTable + HandlerInfo->NumberOfExtractHandler, SectionGuid); + HandlerInfo->ExtractDecodeHandlerTable [HandlerInfo->NumberOfExtractHandler] = DecodeHandler; + HandlerInfo->ExtractGetInfoHandlerTable [HandlerInfo->NumberOfExtractHandler++] = GetInfoHandler; + + return RETURN_SUCCESS; +} + +/** + Retrieves a GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to retrieve and return 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 any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler + of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to retrieve the OututBufferSize, ScratchSize, and Attributes values. The return status from the handler of + type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER is returned. + + 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 Successfully retrieved the required information. + @retval RETURN_UNSUPPORTED The GUID from the section specified by InputSection does not match any of + the GUIDs registered with ExtractGuidedSectionRegisterHandlers(). + @retval Others The return status from the handler associated with the GUID retrieved from + the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + UINT32 Index; + RETURN_STATUS Status; + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + EFI_GUID *SectionDefinitionGuid; + + // + // Check input parameter + // + ASSERT (InputSection != NULL); + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + // + // Get all registered handler information. + // + Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) { + // + // Call the match handler to get information for the input section data. + // + return HandlerInfo->ExtractGetInfoHandlerTable [Index] ( + InputSection, + OutputBufferSize, + ScratchBufferSize, + SectionAttribute + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves the GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to decode the data in a GUIDed section and return the result in a caller + allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler + of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to decode InputSection 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 a caller + allocated buffer specified by OutputBuffer. This function is responsible for computing the EFI_AUTH_STATUS_PLATFORM_OVERRIDE + bit of in AuthenticationStatus. The return status from the handler of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER is returned. + + 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. + + @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 +ExtractGuidedSectionDecode ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + IN VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + UINT32 Index; + RETURN_STATUS Status; + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + EFI_GUID *SectionDefinitionGuid; + + // + // Check input parameter + // + ASSERT (InputSection != NULL); + ASSERT (OutputBuffer != NULL); + ASSERT (AuthenticationStatus != NULL); + + // + // Get all registered handler information. + // + Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered Extract handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) { + // + // Call the match handler to extract raw data for the input guided section. + // + return HandlerInfo->ExtractDecodeHandlerTable [Index] ( + InputSection, + OutputBuffer, + ScratchBuffer, + AuthenticationStatus + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and + EXTRACT_GUIDED_SECTION_DECODE_HANDLER for a specific GUID section type. + + Retrieves the handlers associated with SectionGuid and returns them in + GetInfoHandler and DecodeHandler. + + If the GUID value specified by SectionGuid has not been registered, then + return RETURN_NOT_FOUND. + + If SectionGuid is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the handlersof the GUIDed + section type being retrieved. + @param[out] GetInfoHandler Pointer to a function that 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. + This is an optional parameter that may be NULL. If it is NULL, then + the previously registered handler is not returned. + @param[out] DecodeHandler Pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. This is an optional parameter that may be NULL. + If it is NULL, then the previously registered handler is not returned. + + @retval RETURN_SUCCESS The handlers were retrieved. + @retval RETURN_NOT_FOUND No handlers have been registered with the specified GUID. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetHandlers ( + IN CONST GUID *SectionGuid, + OUT EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *GetInfoHandler, OPTIONAL + OUT EXTRACT_GUIDED_SECTION_DECODE_HANDLER *DecodeHandler OPTIONAL + ) +{ + UINT32 Index; + RETURN_STATUS Status; + EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + // + // Check input parameter + // + ASSERT (SectionGuid != NULL); + + // + // Get the registered handler information + // + Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) { + + // + // If the guided handler has been registered before, then return the registered handlers. + // + if (GetInfoHandler != NULL) { + *GetInfoHandler = HandlerInfo->ExtractGetInfoHandlerTable[Index]; + } + if (DecodeHandler != NULL) { + *DecodeHandler = HandlerInfo->ExtractDecodeHandlerTable[Index]; + } + return RETURN_SUCCESS; + } + } + return RETURN_NOT_FOUND; +} diff --git a/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf new file mode 100644 index 000000000..a152c3117 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf @@ -0,0 +1,49 @@ +## @file +# Base ExtractGuidedSection Library. +# This instance can also be used in SEC phase only when the memory is ready in SEC phase. +# PCD PcdGuidedExtractHandlerTableAddress points to the available pysical memory space +# that is used to store Guided Extract Handlers. +# Note: A driver of type DXE_RUNTIME_DRIVER can use this ExtractGuidedSectionLib +# in their initialization without any issues. They only have to be careful in +# the implementation of runtime services, because this BASE library instance doesn't +# convert the address pointed by PcdGuidedExtractHandlerTableAddress to the virtual address. +# And a driver should use this ExtractGuidedSectionLib to do implementation internally, also +# this ExtractGuidedSectionLib couldn't be used for guided section extraction that is required +# by PEI and DXE core for recovery or capsule image processing, etc. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseExtractGuidedSectionLib + MODULE_UNI_FILE = BaseExtractGuidedSectionLib.uni + FILE_GUID = 4e3236e9-d1c8-4c04-a89f-26f1c44b2592 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ExtractGuidedSectionLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + BaseExtractGuidedSectionLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + PcdLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni new file mode 100644 index 000000000..0793c6373 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni @@ -0,0 +1,22 @@ +// /** @file +// Base ExtractGuidedSection Library. +// +// This instance can also be used in SEC phase only when the memory is ready in SEC phase. +// PCD PcdGuidedExtractHandlerTableAddress points to the available pysical memory space +// that is used to store Guided Extract Handlers. +// Note: A driver of type DXE_RUNTIME_DRIVER can use this ExtractGuidedSectionLib +// in their initialization without any issues. They only have to be careful in +// the implementation of runtime services, because this BASE library instance doesn't +// convert the address pointed by PcdGuidedExtractHandlerTableAddress to the virtual address. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Base ExtractGuidedSection Library" + +#string STR_MODULE_DESCRIPTION #language en-US "This instance can also be used in the SEC phase only when the memory is ready in the SEC phase. PCD PcdGuidedExtractHandlerTableAddress points to the available physical memory space that is used to store Guided Extract Handlers. Note: A driver of type DXE_RUNTIME_DRIVER can use this ExtractGuidedSectionLib in its initialization without any issues. Be careful in the implementation of runtime services, because this BASE library instance doesn't convert the address pointed by PcdGuidedExtractHandlerTableAddress to the virtual address." + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S new file mode 100644 index 000000000..00f1abec1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S @@ -0,0 +1,142 @@ +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# + +.text +.align 3 + +GCC_ASM_EXPORT(MmioRead8Internal) +GCC_ASM_EXPORT(MmioWrite8Internal) +GCC_ASM_EXPORT(MmioRead16Internal) +GCC_ASM_EXPORT(MmioWrite16Internal) +GCC_ASM_EXPORT(MmioRead32Internal) +GCC_ASM_EXPORT(MmioWrite32Internal) +GCC_ASM_EXPORT(MmioRead64Internal) +GCC_ASM_EXPORT(MmioWrite64Internal) + +// +// Reads an 8-bit MMIO register. +// +// Reads the 8-bit MMIO register specified by Address. The 8-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead8Internal): + ldrb w0, [x0] + dmb ld + ret + +// +// Writes an 8-bit MMIO register. +// +// Writes the 8-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite8Internal): + dmb st + strb w1, [x0] + ret + +// +// Reads a 16-bit MMIO register. +// +// Reads the 16-bit MMIO register specified by Address. The 16-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead16Internal): + ldrh w0, [x0] + dmb ld + ret + +// +// Writes a 16-bit MMIO register. +// +// Writes the 16-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite16Internal): + dmb st + strh w1, [x0] + ret + +// +// Reads a 32-bit MMIO register. +// +// Reads the 32-bit MMIO register specified by Address. The 32-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead32Internal): + ldr w0, [x0] + dmb ld + ret + +// +// Writes a 32-bit MMIO register. +// +// Writes the 32-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite32Internal): + dmb st + str w1, [x0] + ret + +// +// Reads a 64-bit MMIO register. +// +// Reads the 64-bit MMIO register specified by Address. The 64-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead64Internal): + ldr x0, [x0] + dmb ld + ret + +// +// Writes a 64-bit MMIO register. +// +// Writes the 64-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite64Internal): + dmb st + str x1, [x0] + ret diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm new file mode 100644 index 000000000..49a0f422d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm @@ -0,0 +1,143 @@ +; +; Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + + +AREA IoLibMmio, CODE, READONLY + +EXPORT MmioRead8Internal +EXPORT MmioWrite8Internal +EXPORT MmioRead16Internal +EXPORT MmioWrite16Internal +EXPORT MmioRead32Internal +EXPORT MmioWrite32Internal +EXPORT MmioRead64Internal +EXPORT MmioWrite64Internal + +; +; Reads an 8-bit MMIO register. +; +; Reads the 8-bit MMIO register specified by Address. The 8-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead8Internal + ldrb w0, [x0] + dmb ld + ret + +; +; Writes an 8-bit MMIO register. +; +; Writes the 8-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite8Internal + dmb st + strb w1, [x0] + ret + +; +; Reads a 16-bit MMIO register. +; +; Reads the 16-bit MMIO register specified by Address. The 16-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead16Internal + ldrh w0, [x0] + dmb ld + ret + +; +; Writes a 16-bit MMIO register. +; +; Writes the 16-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite16Internal + dmb st + strh w1, [x0] + ret + +; +; Reads a 32-bit MMIO register. +; +; Reads the 32-bit MMIO register specified by Address. The 32-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead32Internal + ldr w0, [x0] + dmb ld + ret + +; +; Writes a 32-bit MMIO register. +; +; Writes the 32-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite32Internal + dmb st + str w1, [x0] + ret + +; +; Reads a 64-bit MMIO register. +; +; Reads the 64-bit MMIO register specified by Address. The 64-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead64Internal + ldr x0, [x0] + dmb ld + ret + +; +; Writes a 64-bit MMIO register. +; +; Writes the 64-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite64Internal + dmb st + str x1, [x0] + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S new file mode 100644 index 000000000..f82325769 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S @@ -0,0 +1,141 @@ +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# + +GCC_ASM_EXPORT(MmioRead8Internal) +GCC_ASM_EXPORT(MmioWrite8Internal) +GCC_ASM_EXPORT(MmioRead16Internal) +GCC_ASM_EXPORT(MmioWrite16Internal) +GCC_ASM_EXPORT(MmioRead32Internal) +GCC_ASM_EXPORT(MmioWrite32Internal) +GCC_ASM_EXPORT(MmioRead64Internal) +GCC_ASM_EXPORT(MmioWrite64Internal) + +// +// Reads an 8-bit MMIO register. +// +// Reads the 8-bit MMIO register specified by Address. The 8-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead8Internal): + ldrb r0, [r0] + dmb + bx lr + +// +// Writes an 8-bit MMIO register. +// +// Writes the 8-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite8Internal): + dmb st + strb r1, [r0] + bx lr + +// +// Reads a 16-bit MMIO register. +// +// Reads the 16-bit MMIO register specified by Address. The 16-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead16Internal): + ldrh r0, [r0] + dmb + bx lr + +// +// Writes a 16-bit MMIO register. +// +// Writes the 16-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite16Internal): + dmb st + strh r1, [r0] + bx lr + +// +// Reads a 32-bit MMIO register. +// +// Reads the 32-bit MMIO register specified by Address. The 32-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead32Internal): + ldr r0, [r0] + dmb + bx lr + +// +// Writes a 32-bit MMIO register. +// +// Writes the 32-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite32Internal): + dmb st + str r1, [r0] + bx lr + +// +// Reads a 64-bit MMIO register. +// +// Reads the 64-bit MMIO register specified by Address. The 64-bit read value is +// returned. This function must guarantee that all MMIO read and write +// operations are serialized. +// +// @param Address The MMIO register to read. +// +// @return The value read. +// +ASM_PFX(MmioRead64Internal): + ldr r1, [r0, #4] + ldr r0, [r0] + dmb + bx lr + +// +// Writes a 64-bit MMIO register. +// +// Writes the 64-bit MMIO register specified by Address with the value specified +// by Value and returns Value. This function must guarantee that all MMIO read +// and write operations are serialized. +// +// @param Address The MMIO register to write. +// @param Value The value to write to the MMIO register. +// +ASM_PFX(MmioWrite64Internal): + dmb st + str r2, [r0] + str r3, [r0, #4] + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm new file mode 100644 index 000000000..5a423df16 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm @@ -0,0 +1,145 @@ +; +; Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + + +AREA IoLibMmio, CODE, READONLY + +EXPORT MmioRead8Internal +EXPORT MmioWrite8Internal +EXPORT MmioRead16Internal +EXPORT MmioWrite16Internal +EXPORT MmioRead32Internal +EXPORT MmioWrite32Internal +EXPORT MmioRead64Internal +EXPORT MmioWrite64Internal + +; +; Reads an 8-bit MMIO register. +; +; Reads the 8-bit MMIO register specified by Address. The 8-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead8Internal + ldrb r0, [r0] + dmb + bx lr + +; +; Writes an 8-bit MMIO register. +; +; Writes the 8-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite8Internal + dmb st + strb r1, [r0] + bx lr + +; +; Reads a 16-bit MMIO register. +; +; Reads the 16-bit MMIO register specified by Address. The 16-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead16Internal + ldrh r0, [r0] + dmb + bx lr + +; +; Writes a 16-bit MMIO register. +; +; Writes the 16-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite16Internal + dmb st + strh r1, [r0] + bx lr + +; +; Reads a 32-bit MMIO register. +; +; Reads the 32-bit MMIO register specified by Address. The 32-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead32Internal + ldr r0, [r0] + dmb + bx lr + +; +; Writes a 32-bit MMIO register. +; +; Writes the 32-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite32Internal + dmb st + str r1, [r0] + bx lr + +; +; Reads a 64-bit MMIO register. +; +; Reads the 64-bit MMIO register specified by Address. The 64-bit read value is +; returned. This function must guarantee that all MMIO read and write +; operations are serialized. +; +; @param Address The MMIO register to read. +; +; @return The value read. +; +MmioRead64Internal + ldr r1, [r0, #4] + ldr r0, [r0] + dmb + bx lr + +; +; Writes a 64-bit MMIO register. +; +; Writes the 64-bit MMIO register specified by Address with the value specified +; by Value and returns Value. This function must guarantee that all MMIO read +; and write operations are serialized. +; +; @param Address The MMIO register to write. +; @param Value The value to write to the MMIO register. +; +MmioWrite64Internal + dmb st + str r2, [r0] + str r3, [r0, #4] + bx lr + + END diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf new file mode 100644 index 000000000..690b95d44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf @@ -0,0 +1,69 @@ +## @file +# Instance of I/O Library using compiler intrinsics. +# +# I/O Library that uses compiler intrinsics to perform IN and OUT instructions +# for IA-32 and x64. On IPF, I/O port requests are translated into MMIO requests. +# MMIO requests are forwarded directly to memory. For EBC, I/O port requests +# ASSERT(). For ARM, AARCH64 and RISCV64, this I/O library only provides non I/O +# read and write. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.
+# Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseIoLibIntrinsic + MODULE_UNI_FILE = BaseIoLibIntrinsic.uni + FILE_GUID = 926c9cd0-4bb8-479b-9ac4-8a2a23f85307 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources] + IoLibMmioBuffer.c + BaseIoLibIntrinsicInternal.h + IoHighLevel.c + +[Sources.IA32] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLib.c + Ia32/IoFifo.nasm + +[Sources.X64] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLib.c + X64/IoFifo.nasm + +[Sources.EBC] + IoLibEbc.c + IoLib.c + +[Sources.ARM] + IoLibNoIo.c + +[Sources.AARCH64] + IoLibNoIo.c + +[Sources.RISCV64] + IoLibNoIo.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni new file mode 100644 index 000000000..0f848bc5d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni @@ -0,0 +1,19 @@ +// /** @file +// Instance of I/O Library using compiler intrinsics. +// +// I/O Library that uses compiler intrinsics to perform IN and OUT instructions +// for IA-32 and x64. On IPF, I/O port requests are translated into MMIO requests. +// MMIO requests are forwarded directly to memory. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of I/O Library using compiler intrinsics" + +#string STR_MODULE_DESCRIPTION #language en-US "I/O Library that uses compiler intrinsics to perform IN and OUT instructions for IA-32 and x64. On IPF, I/O port requests are translated into MMIO requests. MMIO requests are forwarded directly to memory." + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf new file mode 100644 index 000000000..ad68f841f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf @@ -0,0 +1,46 @@ +## @file +# Instance of I/O Library using KVM/ARM safe assembler routines +# +# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = BaseIoLibIntrinsicArmVirt + MODULE_UNI_FILE = BaseIoLibIntrinsicArmVirt.uni + FILE_GUID = 217102b4-b465-4a1d-a2de-93dd385ec480 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib + +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + IoLibMmioBuffer.c + BaseIoLibIntrinsicInternal.h + IoHighLevel.c + +[Sources.ARM] + IoLibArmVirt.c + Arm/ArmVirtMmio.S | GCC + Arm/ArmVirtMmio.asm | RVCT + +[Sources.AARCH64] + IoLibArmVirt.c + AArch64/ArmVirtMmio.S | GCC + AArch64/ArmVirtMmio.asm | MSFT + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni new file mode 100644 index 000000000..758499c28 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of I/O Library using KVM/ARM safe assembler routines +// +// Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// Copyright (c) 2017, AMD Incorporated. All rights reserved.
+// Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of I/O Library using KVM/ARM safe assembler routines" + +#string STR_MODULE_DESCRIPTION #language en-US "I/O Library that uses assembler routines to perform MMIO accesses, to prevent link time code generation under LTO from emitting instructions that KVM on ARM cannot deal with." + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h new file mode 100644 index 000000000..1aae45fa8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h @@ -0,0 +1,21 @@ +/** @file + Common header file shared by all source files. + + This file includes package header files, dependent library classes. + + Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __BASEIOLIB_INTRINSIC_INTERNAL_H_ +#define __BASEIOLIB_INTRINSIC_INTERNAL_H_ + + + +#include + +#include +#include +#include + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf new file mode 100644 index 000000000..86a07e60f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf @@ -0,0 +1,52 @@ +## @file +# Instance of I/O Library using compiler intrinsics. +# +# I/O Library that uses compiler intrinsics to perform IN and OUT instructions +# for IA-32 and x64. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseIoLibIntrinsicSev + MODULE_UNI_FILE = BaseIoLibIntrinsic.uni + FILE_GUID = 93742f95-6e71-4581-b600-8e1da443f95a + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + IoLibMmioBuffer.c + BaseIoLibIntrinsicInternal.h + IoHighLevel.c + +[Sources.IA32] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLib.c + Ia32/IoFifoSev.nasm + +[Sources.X64] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLib.c + X64/IoFifoSev.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm new file mode 100644 index 000000000..a4ae1a005 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm @@ -0,0 +1,131 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo8 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo8) +ASM_PFX(IoReadFifo8): + push edi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] +rep insb + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo16 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo16) +ASM_PFX(IoReadFifo16): + push edi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] +rep insw + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo32 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo32) +ASM_PFX(IoReadFifo32): + push edi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] +rep insd + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo8 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo8) +ASM_PFX(IoWriteFifo8): + push esi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] +rep outsb + pop esi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo16 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo16) +ASM_PFX(IoWriteFifo16): + push esi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] +rep outsw + pop esi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo32 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo32) +ASM_PFX(IoWriteFifo32): + push esi + cld + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] +rep outsd + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm new file mode 100644 index 000000000..63a4771d3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm @@ -0,0 +1,293 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; Check whether we need to unroll the String I/O under SEV guest +; +; Return // eax (1 - unroll, 0 - no unroll) +;------------------------------------------------------------------------------ +global ASM_PFX(SevNoRepIo) +ASM_PFX(SevNoRepIo): + + ; CPUID clobbers ebx, ecx and edx + push ebx + push ecx + push edx + + ; Check if we are running under hypervisor + ; CPUID(1).ECX Bit 31 + mov eax, 1 + cpuid + bt ecx, 31 + jnc @UseRepIo + + ; Check if we have Memory encryption CPUID leaf + mov eax, 0x80000000 + cpuid + cmp eax, 0x8000001f + jl @UseRepIo + + ; Check for memory encryption feature: + ; CPUID Fn8000_001F[EAX] - Bit 1 + ; + mov eax, 0x8000001f + cpuid + bt eax, 1 + jnc @UseRepIo + + ; Check if memory encryption is enabled + ; MSR_0xC0010131 - Bit 0 (SEV enabled) + ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled) + mov ecx, 0xc0010131 + rdmsr + + ; Check for (SevEsEnabled == 0 && SevEnabled == 1) + and eax, 3 + cmp eax, 1 + je @SevNoRepIo_Done + +@UseRepIo: + xor eax, eax + +@SevNoRepIo_Done: + pop edx + pop ecx + pop ebx + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo8 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo8) +ASM_PFX(IoReadFifo8): + push edi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo8_NoRep + + cld + rep insb + jmp @IoReadFifo8_Done + +@IoReadFifo8_NoRep: + jecxz @IoReadFifo8_Done + +@IoReadFifo8_Loop: + in al, dx + mov byte [edi], al + inc edi + loop @IoReadFifo8_Loop + +@IoReadFifo8_Done: + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo16 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo16) +ASM_PFX(IoReadFifo16): + push edi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo16_NoRep + + cld + rep insw + jmp @IoReadFifo16_Done + +@IoReadFifo16_NoRep: + jecxz @IoReadFifo16_Done + +@IoReadFifo16_Loop: + in ax, dx + mov word [edi], ax + add edi, 2 + loop @IoReadFifo16_Loop + +@IoReadFifo16_Done: + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo32 ( +; IN UINTN Port, +; IN UINTN Size, +; OUT VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo32) +ASM_PFX(IoReadFifo32): + push edi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov edi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo32_NoRep + + cld + rep insd + jmp @IoReadFifo32_Done + +@IoReadFifo32_NoRep: + jecxz @IoReadFifo32_Done + +@IoReadFifo32_Loop: + in eax, dx + mov dword [edi], eax + add edi, 4 + loop @IoReadFifo32_Loop + +@IoReadFifo32_Done: + pop edi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo8 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo8) +ASM_PFX(IoWriteFifo8): + push esi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo8_NoRep + + cld + rep outsb + jmp @IoWriteFifo8_Done + +@IoWriteFifo8_NoRep: + jecxz @IoWriteFifo8_Done + +@IoWriteFifo8_Loop: + mov al, byte [esi] + out dx, al + inc esi + loop @IoWriteFifo8_Loop + +@IoWriteFifo8_Done: + pop esi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo16 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo16) +ASM_PFX(IoWriteFifo16): + push esi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo16_NoRep + + cld + rep outsw + jmp @IoWriteFifo16_Done + +@IoWriteFifo16_NoRep: + jecxz @IoWriteFifo16_Done + +@IoWriteFifo16_Loop: + mov ax, word [esi] + out dx, ax + add esi, 2 + loop @IoWriteFifo16_Loop + +@IoWriteFifo16_Done: + pop esi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo32 ( +; IN UINTN Port, +; IN UINTN Size, +; IN VOID *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo32) +ASM_PFX(IoWriteFifo32): + push esi + mov dx, [esp + 8] + mov ecx, [esp + 12] + mov esi, [esp + 16] + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo32_NoRep + + cld + rep outsd + jmp @IoWriteFifo32_Done + +@IoWriteFifo32_NoRep: + jecxz @IoWriteFifo32_Done + +@IoWriteFifo32_Loop: + mov eax, dword [esi] + out dx, eax + add esi, 4 + loop @IoWriteFifo32_Loop + +@IoWriteFifo32_Done: + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c new file mode 100644 index 000000000..559f56931 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c @@ -0,0 +1,2350 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + The following IoLib instances contain the same copy of this file: + + BaseIoLibIntrinsic + DxeIoLibCpuIo + PeiIoLibCpuIo + +**/ + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads an 8-bit I/O port, performs a bitwise OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) | OrData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) & AndData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) ((IoRead8 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra bits left in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra bits left in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra bits left in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) | OrData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) & AndData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) ((IoRead16 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + bits left in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra bits left in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra bits left in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra bits left in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + bits left in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra bits left in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra bits left in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra bits left in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + bits left in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra bits left in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra bits left in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra bits left in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) | OrData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) & AndData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) ((MmioRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra bits left in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra bits left in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra bits left in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) | OrData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) & AndData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) ((MmioRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra bits left in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra bits left in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra bits left in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra bits left in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra bits left in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra bits left in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra bits left in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra bits left in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra bits left in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c new file mode 100644 index 000000000..a6bbc9254 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c @@ -0,0 +1,311 @@ +/** @file + Common I/O Library routines. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + UINT8 Value; + + MemoryFence (); + Value = *(volatile UINT8*)Address; + MemoryFence (); + + return Value; +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + MemoryFence (); + *(volatile UINT8*)Address = Value; + MemoryFence (); + + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + UINT16 Value; + + ASSERT ((Address & 1) == 0); + + MemoryFence (); + Value = *(volatile UINT16*)Address; + MemoryFence (); + + return Value; +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT ((Address & 1) == 0); + + MemoryFence (); + *(volatile UINT16*)Address = Value; + MemoryFence (); + + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + UINT32 Value; + + ASSERT ((Address & 3) == 0); + + MemoryFence (); + Value = *(volatile UINT32*)Address; + MemoryFence (); + + return Value; +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT ((Address & 3) == 0); + + MemoryFence (); + *(volatile UINT32*)Address = Value; + MemoryFence (); + + return Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + UINT64 Value; + + ASSERT ((Address & 7) == 0); + + MemoryFence (); + Value = *(volatile UINT64*)Address; + MemoryFence (); + + return Value; +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + ASSERT ((Address & 7) == 0); + + MemoryFence (); + *(volatile UINT64*)Address = Value; + MemoryFence (); + + return Value; +} + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c new file mode 100644 index 000000000..9715705ee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c @@ -0,0 +1,727 @@ +/** @file + I/O Library for ARM. + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8Internal ( + IN UINTN Address + ); + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +VOID +EFIAPI +MmioWrite8Internal ( + IN UINTN Address, + IN UINT8 Value + ); + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16Internal ( + IN UINTN Address + ); + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +VOID +EFIAPI +MmioWrite16Internal ( + IN UINTN Address, + IN UINT16 Value + ); + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32Internal ( + IN UINTN Address + ); + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +VOID +EFIAPI +MmioWrite32Internal ( + IN UINTN Address, + IN UINT32 Value + ); + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64Internal ( + IN UINTN Address + ); + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +VOID +EFIAPI +MmioWrite64Internal ( + IN UINTN Address, + IN UINT64 Value + ); + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + return MmioRead8Internal (Address); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + MmioWrite8Internal (Address, Value); + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 1) == 0); + + return MmioRead16Internal (Address); +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT ((Address & 1) == 0); + + MmioWrite16Internal (Address, Value); + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 3) == 0); + + return MmioRead32Internal (Address); +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT ((Address & 3) == 0); + + MmioWrite32Internal (Address, Value); + return Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 7) == 0); + + return MmioRead64Internal (Address); +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + ASSERT ((Address & 7) == 0); + + MmioWrite64Internal (Address, Value); + return Value; +} diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c new file mode 100644 index 000000000..98c774fa7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c @@ -0,0 +1,336 @@ +/** @file + I/O Library for EBC. + + EBC does not support port I/O. All APIs in this file ASSERT(). + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c new file mode 100644 index 000000000..b3a1a2025 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c @@ -0,0 +1,184 @@ +/** @file + I/O Library. This file has compiler specifics for GCC as there is no + ANSI C standard for doing IO. + + GCC - uses EFIAPI assembler. __asm__ calls GAS. __volatile__ makes sure the + compiler puts the assembler in this exact location. The complex GNUC + operations are not optimzed. It would be possible to also write these + with EFIAPI assembler. + + We don't advocate putting compiler specifics in libraries or drivers but there + is no other way to make this work. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + UINT8 Data; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + UINT16 Data; + + ASSERT ((Port & 1) == 0); + __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT ((Port & 1) == 0); + __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + + ASSERT ((Port & 3) == 0); + __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT ((Port & 3) == 0); + __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value; +} + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c new file mode 100644 index 000000000..6059bab6b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c @@ -0,0 +1,405 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseIoLibIntrinsicInternal.h" + +/** + Copy data from the MMIO region to system memory by using 8-bit access. + + Copy data from the MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 8-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = Buffer; + + while (Length-- != 0) { + *(Buffer++) = MmioRead8 (StartAddress++); + } + + return ReturnBuffer; +} + +/** + Copy data from the MMIO region to system memory by using 16-bit access. + + Copy data from the MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 16-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + +/** + Copy data from the MMIO region to system memory by using 32-bit access. + + Copy data from the MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 32-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from the MMIO region to system memory by using 64-bit access. + + Copy data from the MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 64-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead64 (StartAddress); + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to the MMIO region by using 8-bit access. + + Copy data from system memory specified by Buffer to the MMIO region specified + by starting address StartAddress by using 8-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioWriteBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT8 *Buffer + ) +{ + VOID* ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = (UINT8 *) Buffer; + + while (Length-- != 0) { + MmioWrite8 (StartAddress++, *(Buffer++)); + } + + return ReturnBuffer; + +} + +/** + Copy data from system memory to the MMIO region by using 16-bit access. + + Copy data from system memory specified by Buffer to the MMIO region specified + by starting address StartAddress by using 16-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioWriteBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = (UINT16 *) Buffer; + + while (Length != 0) { + MmioWrite16 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to the MMIO region by using 32-bit access. + + Copy data from system memory specified by Buffer to the MMIO region specified + by starting address StartAddress by using 32-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioWriteBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = (UINT32 *) Buffer; + + while (Length != 0) { + MmioWrite32 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from system memory to the MMIO region by using 64-bit access. + + Copy data from system memory specified by Buffer to the MMIO region specified + by starting address StartAddress by using 64-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioWriteBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = (UINT64 *) Buffer; + + while (Length != 0) { + MmioWrite64 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c new file mode 100644 index 000000000..769dddfce --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c @@ -0,0 +1,222 @@ +/** @file + I/O Library. This file has compiler specifics for Microsft C as there is no + ANSI C standard for doing IO. + + MSC - uses intrinsic functions and the optimize will remove the function call + overhead. + + We don't advocate putting compiler specifics in libraries or drivers but there + is no other way to make this work. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include "BaseIoLibIntrinsicInternal.h" + +// +// Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +// + +int _inp (unsigned short port); +unsigned short _inpw (unsigned short port); +unsigned long _inpd (unsigned short port); +int _outp (unsigned short port, int databyte ); +unsigned short _outpw (unsigned short port, unsigned short dataword ); +unsigned long _outpd (unsigned short port, unsigned long dataword ); +void _ReadWriteBarrier (void); + +#pragma intrinsic(_inp) +#pragma intrinsic(_inpw) +#pragma intrinsic(_inpd) +#pragma intrinsic(_outp) +#pragma intrinsic(_outpw) +#pragma intrinsic(_outpd) +#pragma intrinsic(_ReadWriteBarrier) + +// +// _ReadWriteBarrier() forces memory reads and writes to complete at the point +// in the call. This is only a hint to the compiler and does emit code. +// In past versions of the compiler, _ReadWriteBarrier was enforced only +// locally and did not affect functions up the call tree. In Visual C++ +// 2005, _ReadWriteBarrier is enforced all the way up the call tree. +// + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + UINT8 Value; + + _ReadWriteBarrier (); + Value = (UINT8)_inp ((UINT16)Port); + _ReadWriteBarrier (); + return Value; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + _ReadWriteBarrier (); + (UINT8)_outp ((UINT16)Port, Value); + _ReadWriteBarrier (); + return Value; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + UINT16 Value; + + ASSERT ((Port & 1) == 0); + _ReadWriteBarrier (); + Value = _inpw ((UINT16)Port); + _ReadWriteBarrier (); + return Value; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT ((Port & 1) == 0); + _ReadWriteBarrier (); + _outpw ((UINT16)Port, Value); + _ReadWriteBarrier (); + return Value; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + UINT32 Value; + + ASSERT ((Port & 3) == 0); + _ReadWriteBarrier (); + Value = _inpd ((UINT16)Port); + _ReadWriteBarrier (); + return Value; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT ((Port & 3) == 0); + _ReadWriteBarrier (); + _outpd ((UINT16)Port, Value); + _ReadWriteBarrier (); + return Value; +} diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c new file mode 100644 index 000000000..a107136a7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c @@ -0,0 +1,595 @@ +/** @file + I/O library for non I/O read and write access (memory map I/O read and + write only) architecture, such as ARM and RISC-V processor. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +// +// Include common header file for this module. +// +#include "BaseIoLibIntrinsicInternal.h" + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + return Value; +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + UINT8 Value; + + Value = *(volatile UINT8*)Address; + return Value; +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + *(volatile UINT8*)Address = Value; + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + UINT16 Value; + + ASSERT ((Address & 1) == 0); + Value = *(volatile UINT16*)Address; + return Value; +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT ((Address & 1) == 0); + *(volatile UINT16*)Address = Value; + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + UINT32 Value; + + ASSERT ((Address & 3) == 0); + Value = *(volatile UINT32*)Address; + return Value; +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT ((Address & 3) == 0); + *(volatile UINT32*)Address = Value; + return Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + UINT64 Value; + + ASSERT ((Address & 7) == 0); + Value = *(volatile UINT64*)Address; + return Value; +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + ASSERT ((Address & 7) == 0); + *(volatile UINT64*)Address = Value; + return Value; +} + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm new file mode 100644 index 000000000..d459072f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm @@ -0,0 +1,120 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo8 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo8) +ASM_PFX(IoReadFifo8): + cld + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi +rep insb + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo16 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo16) +ASM_PFX(IoReadFifo16): + cld + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi +rep insw + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo32 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo32) +ASM_PFX(IoReadFifo32): + cld + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi +rep insd + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo8 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo8) +ASM_PFX(IoWriteFifo8): + cld + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi +rep outsb + mov rsi, r8 ; restore rsi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo16 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo16) +ASM_PFX(IoWriteFifo16): + cld + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi +rep outsw + mov rsi, r8 ; restore rsi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo32 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo32) +ASM_PFX(IoWriteFifo32): + cld + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi +rep outsd + mov rsi, r8 ; restore rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm new file mode 100644 index 000000000..106f8881c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm @@ -0,0 +1,282 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; Check whether we need to unroll the String I/O in SEV guest +; +; Return // eax (1 - unroll, 0 - no unroll) +;------------------------------------------------------------------------------ +global ASM_PFX(SevNoRepIo) +ASM_PFX(SevNoRepIo): + + ; CPUID clobbers ebx, ecx and edx + push rbx + push rcx + push rdx + + ; Check if we are runing under hypervisor + ; CPUID(1).ECX Bit 31 + mov eax, 1 + cpuid + bt ecx, 31 + jnc @UseRepIo + + ; Check if we have Memory encryption CPUID leaf + mov eax, 0x80000000 + cpuid + cmp eax, 0x8000001f + jl @UseRepIo + + ; Check for memory encryption feature: + ; CPUID Fn8000_001F[EAX] - Bit 1 + ; + mov eax, 0x8000001f + cpuid + bt eax, 1 + jnc @UseRepIo + + ; Check if memory encryption is enabled + ; MSR_0xC0010131 - Bit 0 (SEV enabled) + ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled) + mov ecx, 0xc0010131 + rdmsr + + ; Check for (SevEsEnabled == 0 && SevEnabled == 1) + and eax, 3 + cmp eax, 1 + je @SevNoRepIo_Done + +@UseRepIo: + xor eax, eax + +@SevNoRepIo_Done: + pop rdx + pop rcx + pop rbx + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo8 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo8) +ASM_PFX(IoReadFifo8): + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo8_NoRep + + cld + rep insb + jmp @IoReadFifo8_Done + +@IoReadFifo8_NoRep: + jrcxz @IoReadFifo8_Done + +@IoReadFifo8_Loop: + in al, dx + mov byte [rdi], al + inc rdi + loop @IoReadFifo8_Loop + +@IoReadFifo8_Done: + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo16 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo16) +ASM_PFX(IoReadFifo16): + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo16_NoRep + + cld + rep insw + jmp @IoReadFifo16_Done + +@IoReadFifo16_NoRep: + jrcxz @IoReadFifo16_Done + +@IoReadFifo16_Loop: + in ax, dx + mov word [rdi], ax + add rdi, 2 + loop @IoReadFifo16_Loop + +@IoReadFifo16_Done: + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoReadFifo32 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; OUT VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoReadFifo32) +ASM_PFX(IoReadFifo32): + xchg rcx, rdx + xchg rdi, r8 ; rdi: buffer address; r8: save rdi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoReadFifo32_NoRep + + cld + rep insd + jmp @IoReadFifo32_Done + +@IoReadFifo32_NoRep: + jrcxz @IoReadFifo32_Done + +@IoReadFifo32_Loop: + in eax, dx + mov dword [rdi], eax + add rdi, 4 + loop @IoReadFifo32_Loop + +@IoReadFifo32_Done: + mov rdi, r8 ; restore rdi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo8 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo8) +ASM_PFX(IoWriteFifo8): + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo8_NoRep + + cld + rep outsb + jmp @IoWriteFifo8_Done + +@IoWriteFifo8_NoRep: + jrcxz @IoWriteFifo8_Done + +@IoWriteFifo8_Loop: + mov al, byte [rsi] + out dx, al + inc rsi + loop @IoWriteFifo8_Loop + +@IoWriteFifo8_Done: + mov rsi, r8 ; restore rsi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo16 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo16) +ASM_PFX(IoWriteFifo16): + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo16_NoRep + + cld + rep outsw + jmp @IoWriteFifo16_Done + +@IoWriteFifo16_NoRep: + jrcxz @IoWriteFifo16_Done + +@IoWriteFifo16_Loop: + mov ax, word [rsi] + out dx, ax + add rsi, 2 + loop @IoWriteFifo16_Loop + +@IoWriteFifo16_Done: + mov rsi, r8 ; restore rsi + ret + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; IoWriteFifo32 ( +; IN UINTN Port, // rcx +; IN UINTN Size, // rdx +; IN VOID *Buffer // r8 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(IoWriteFifo32) +ASM_PFX(IoWriteFifo32): + xchg rcx, rdx + xchg rsi, r8 ; rsi: buffer address; r8: save rsi + + ; Check if we need to unroll String I/O + call ASM_PFX(SevNoRepIo) + test eax, eax + jnz @IoWriteFifo32_NoRep + + cld + rep outsd + jmp @IoWriteFifo32_Done + +@IoWriteFifo32_NoRep: + jrcxz @IoWriteFifo32_Done + +@IoWriteFifo32_Loop: + mov eax, dword [rsi] + out dx, eax + add rsi, 4 + loop @IoWriteFifo32_Loop + +@IoWriteFifo32_Done: + mov rsi, r8 ; restore rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S new file mode 100644 index 000000000..7524fb188 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S @@ -0,0 +1,31 @@ +#------------------------------------------------------------------------------ +# +# CpuBreakpoint() for AArch64 +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(CpuBreakpoint) + +#/** +# Generates a breakpoint on the CPU. +# +# Generates a breakpoint on the CPU. The breakpoint must be implemented such +# that code can resume normal execution after the breakpoint. +# +#**/ +#VOID +#EFIAPI +#CpuBreakpoint ( +# VOID +# ); +# +ASM_PFX(CpuBreakpoint): + svc 0xdbdb // Superviser exception. Takes 16bit arg -> Armv7 had 'swi' here. + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm new file mode 100644 index 000000000..4a5e05def --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; CpuBreakpoint() for AArch64 +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + + EXPORT CpuBreakpoint + AREA BaseLib_LowLevel, CODE, READONLY + +;/** +; Generates a breakpoint on the CPU. +; +; Generates a breakpoint on the CPU. The breakpoint must be implemented such +; that code can resume normal execution after the breakpoint. +; +;**/ +;VOID +;EFIAPI +;CpuBreakpoint ( +; VOID +; ); +; +CpuBreakpoint + svc 0xdbdb // Superviser exception. Takes 16bit arg -> Armv7 had 'swi' here. + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S new file mode 100644 index 000000000..f0faf16b0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# DisableInterrupts() for AArch64 +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(DisableInterrupts) + +.set DAIF_WR_IRQ_BIT, (1 << 1) + +#/** +# Disables CPU interrupts. +# +#**/ +#VOID +#EFIAPI +#DisableInterrupts ( +# VOID +# ); +# +ASM_PFX(DisableInterrupts): + msr daifset, #DAIF_WR_IRQ_BIT + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm new file mode 100644 index 000000000..f7be1ea27 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; DisableInterrupts() for AArch64 +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT DisableInterrupts + AREA BaseLib_LowLevel, CODE, READONLY + +DAIF_WR_IRQ_BIT EQU (1 << 1) + +;/** +; Disables CPU interrupts. +; +;**/ +;VOID +;EFIAPI +;DisableInterrupts ( +; VOID +; ); +; +DisableInterrupts + msr daifset, #DAIF_WR_IRQ_BIT + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S new file mode 100644 index 000000000..97eeb13fb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# EnableInterrupts() for AArch64 +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(EnableInterrupts) + +.set DAIF_WR_IRQ_BIT, (1 << 1) + +#/** +# Enables CPU interrupts. +# +#**/ +#VOID +#EFIAPI +#EnableInterrupts ( +# VOID +# ); +# +ASM_PFX(EnableInterrupts): + msr daifclr, #DAIF_WR_IRQ_BIT + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm new file mode 100644 index 000000000..0c3a3103e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; EnableInterrupts() for AArch64 +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT EnableInterrupts + AREA BaseLib_LowLevel, CODE, READONLY + +DAIF_WR_IRQ_BIT EQU (1 << 1) + +;/** +; Enables CPU interrupts. +; +;**/ +;VOID +;EFIAPI +;EnableInterrupts ( +; VOID +; ); +; +EnableInterrupts + msr daifclr, #DAIF_WR_IRQ_BIT + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S new file mode 100644 index 000000000..bf8b829bb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# GetInterruptState() function for AArch64 +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(GetInterruptState) + +.set DAIF_RD_IRQ_BIT, (1 << 7) + +#/** +# Retrieves the current CPU interrupt state. +# +# Returns TRUE is interrupts are currently enabled. Otherwise +# returns FALSE. +# +# @retval TRUE CPU interrupts are enabled. +# @retval FALSE CPU interrupts are disabled. +# +#**/ +# +#BOOLEAN +#EFIAPI +#GetInterruptState ( +# VOID +# ); +# +ASM_PFX(GetInterruptState): + mrs x0, daif + tst x0, #DAIF_RD_IRQ_BIT // Check IRQ mask; set Z=1 if clear/unmasked + cset w0, eq // if Z=1 (eq) return 1, else 0 + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm new file mode 100644 index 000000000..b169db45d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; GetInterruptState() function for AArch64 +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT GetInterruptState + AREA BaseLib_LowLevel, CODE, READONLY + +DAIF_RD_IRQ_BIT EQU (1 << 7) + +;/** +; Retrieves the current CPU interrupt state. +; +; Returns TRUE is interrupts are currently enabled. Otherwise +; returns FALSE. +; +; @retval TRUE CPU interrupts are enabled. +; @retval FALSE CPU interrupts are disabled. +; +;**/ +; +;BOOLEAN +;EFIAPI +;GetInterruptState ( +; VOID +; ); +; +GetInterruptState + mrs x0, daif + mov w0, wzr + tst x0, #DAIF_RD_IRQ_BIT // Check IRQ mask; set Z=1 if clear/unmasked + bne exit // if Z=1 (eq) return 1, else 0 + mov w0, #1 +exit + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S new file mode 100644 index 000000000..e553bd2dc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S @@ -0,0 +1,33 @@ +##------------------------------------------------------------------------------ +# +# MemoryFence() for AArch64 +# +# Copyright (c) 2013, ARM Ltd. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +##------------------------------------------------------------------------------ + +.text +.p2align 2 + +GCC_ASM_EXPORT(MemoryFence) + + +#/** +# Used to serialize load and store operations. +# +# All loads and stores that proceed calls to this function are guaranteed to be +# globally visible when this function returns. +# +#**/ +#VOID +#EFIAPI +#MemoryFence ( +# VOID +# ); +# +ASM_PFX(MemoryFence): + // System wide Data Memory Barrier. + dmb sy + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm new file mode 100644 index 000000000..85bc6c0f9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; MemoryFence() for AArch64 +; +; Copyright (c) 2013, ARM Ltd. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT MemoryFence + AREA BaseLib_LowLevel, CODE, READONLY + +;/** +; Used to serialize load and store operations. +; +; All loads and stores that proceed calls to this function are guaranteed to be +; globally visible when this function returns. +; +;**/ +;VOID +;EFIAPI +;MemoryFence ( +; VOID +; ); +; +MemoryFence + // System wide Data Memory Barrier. + dmb sy + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S new file mode 100644 index 000000000..72cea259e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S @@ -0,0 +1,91 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2009-2013, ARM Ltd. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ +.text +.p2align 3 + +GCC_ASM_EXPORT(SetJump) +GCC_ASM_EXPORT(InternalLongJump) + +#define GPR_LAYOUT \ + REG_PAIR (x19, x20, 0); \ + REG_PAIR (x21, x22, 16); \ + REG_PAIR (x23, x24, 32); \ + REG_PAIR (x25, x26, 48); \ + REG_PAIR (x27, x28, 64); \ + REG_PAIR (x29, x30, 80);/*FP, LR*/ \ + REG_ONE (x16, 96) /*IP0*/ + +#define FPR_LAYOUT \ + REG_PAIR ( d8, d9, 112); \ + REG_PAIR (d10, d11, 128); \ + REG_PAIR (d12, d13, 144); \ + REG_PAIR (d14, d15, 160); + +#/** +# Saves the current CPU context that can be restored with a call to LongJump() and returns 0.# +# +# Saves the current CPU context in the buffer specified by JumpBuffer and returns 0. The initial +# call to SetJump() must always return 0. Subsequent calls to LongJump() cause a non-zero +# value to be returned by SetJump(). +# +# If JumpBuffer is NULL, then ASSERT(). +# For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). +# +# @param JumpBuffer A pointer to CPU context buffer. +# +#**/ +# +#UINTN +#EFIAPI +#SetJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer // X0 +# ); +# +ASM_PFX(SetJump): + mov x16, sp // use IP0 so save SP +#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] + GPR_LAYOUT + FPR_LAYOUT +#undef REG_PAIR +#undef REG_ONE + mov w0, #0 + ret + +#/** +# Restores the CPU context that was saved with SetJump().# +# +# Restores the CPU context from the buffer specified by JumpBuffer. +# This function never returns to the caller. +# Instead is resumes execution based on the state of JumpBuffer. +# +# @param JumpBuffer A pointer to CPU context buffer. +# @param Value The value to return when the SetJump() context is restored. +# +#**/ +#VOID +#EFIAPI +#InternalLongJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, // X0 +# IN UINTN Value // X1 +# ); +# +ASM_PFX(InternalLongJump): +#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] + GPR_LAYOUT + FPR_LAYOUT +#undef REG_PAIR +#undef REG_ONE + mov sp, x16 + cmp w1, #0 + mov w0, #1 + csel w0, w1, w0, ne + // use br not ret, as ret is guaranteed to mispredict + br x30 + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm new file mode 100644 index 000000000..20dd0f1b8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm @@ -0,0 +1,95 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2009-2013, ARM Ltd. All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT SetJump + EXPORT InternalLongJump + AREA BaseLib_LowLevel, CODE, READONLY + +#define GPR_LAYOUT \ + REG_PAIR (x19, x20, #0); \ + REG_PAIR (x21, x22, #16); \ + REG_PAIR (x23, x24, #32); \ + REG_PAIR (x25, x26, #48); \ + REG_PAIR (x27, x28, #64); \ + REG_PAIR (x29, x30, #80);/*FP, LR*/ \ + REG_ONE (x16, #96) /*IP0*/ + +#define FPR_LAYOUT \ + REG_PAIR ( d8, d9, #112); \ + REG_PAIR (d10, d11, #128); \ + REG_PAIR (d12, d13, #144); \ + REG_PAIR (d14, d15, #160); + +;/** +; Saves the current CPU context that can be restored with a call to LongJump() and returns 0.# +; +; Saves the current CPU context in the buffer specified by JumpBuffer and returns 0. The initial +; call to SetJump() must always return 0. Subsequent calls to LongJump() cause a non-zero +; value to be returned by SetJump(). +; +; If JumpBuffer is NULL, then ASSERT(). +; For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). +; +; @param JumpBuffer A pointer to CPU context buffer. +; +;**/ +; +;UINTN +;EFIAPI +;SetJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer // X0 +; ); +; +SetJump + mov x16, sp // use IP0 so save SP +#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] + GPR_LAYOUT + FPR_LAYOUT +#undef REG_PAIR +#undef REG_ONE + mov w0, #0 + ret + +;/** +; Restores the CPU context that was saved with SetJump().# +; +; Restores the CPU context from the buffer specified by JumpBuffer. +; This function never returns to the caller. +; Instead is resumes execution based on the state of JumpBuffer. +; +; @param JumpBuffer A pointer to CPU context buffer. +; @param Value The value to return when the SetJump() context is restored. +; +;**/ +;VOID +;EFIAPI +;InternalLongJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, // X0 +; IN UINTN Value // X1 +; ); +; +InternalLongJump +#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] + GPR_LAYOUT + FPR_LAYOUT +#undef REG_PAIR +#undef REG_ONE + mov sp, x16 + cmp w1, #0 + mov w0, #1 + beq exit + mov w0, w1 +exit + // use br not ret, as ret is guaranteed to mispredict + br x30 + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED + + END + diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S new file mode 100644 index 000000000..a20d6aed0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S @@ -0,0 +1,33 @@ +##------------------------------------------------------------------------------ +# +# SpeculationBarrier() for AArch64 +# +# Copyright (c) 2019, Linaro Ltd. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +##------------------------------------------------------------------------------ + +.text +.p2align 2 + +GCC_ASM_EXPORT(SpeculationBarrier) + + +#/** +# Uses as a barrier to stop speculative execution. +# +# Ensures that no later instruction will execute speculatively, until all prior +# instructions have completed. +# +#**/ +#VOID +#EFIAPI +#SpeculationBarrier ( +# VOID +# ); +# +ASM_PFX(SpeculationBarrier): + dsb sy + isb + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm new file mode 100644 index 000000000..cafbe2bf2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; SpeculationBarrier() for AArch64 +; +; Copyright (c) 2019, Linaro Ltd. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT SpeculationBarrier + AREA BaseLib_LowLevel, CODE, READONLY + +;/** +; Uses as a barrier to stop speculative execution. +; +; Ensures that no later instruction will execute speculatively, until all prior +; instructions have completed. +; +;**/ +;VOID +;EFIAPI +;SpeculationBarrier ( +; VOID +; ); +; +SpeculationBarrier + dsb sy + isb + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S new file mode 100644 index 000000000..f3bce6a09 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S @@ -0,0 +1,65 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Limited. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.align 5 + +GCC_ASM_EXPORT(InternalSwitchStackAsm) +GCC_ASM_EXPORT(CpuPause) + +#/** +# +# This allows the caller to switch the stack and goes to the new entry point +# +# @param EntryPoint The pointer to the location to enter +# @param Context Parameter to pass in +# @param Context2 Parameter2 to pass in +# @param NewStack New Location of the stack +# +# @return Nothing. Goes to the Entry Point passing in the new parameters +# +#**/ +#VOID +#EFIAPI +#InternalSwitchStackAsm ( +# SWITCH_STACK_ENTRY_POINT EntryPoint, +# VOID *Context, +# VOID *Context2, +# VOID *NewStack +# ); +# +ASM_PFX(InternalSwitchStackAsm): + mov x29, #0 + mov x30, x0 + mov sp, x3 + mov x0, x1 + mov x1, x2 + ret + +#/** +# +# Requests CPU to pause for a short period of time. +# +# Requests CPU to pause for a short period of time. Typically used in MP +# systems to prevent memory starvation while waiting for a spin lock. +# +#**/ +#VOID +#EFIAPI +#CpuPause ( +# VOID +# ) +# +ASM_PFX(CpuPause): + nop + nop + nop + nop + nop + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm new file mode 100644 index 000000000..56dce5cbe --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; Portions copyright (c) 2011 - 2013, ARM Limited. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT InternalSwitchStackAsm + EXPORT CpuPause + AREA BaseLib_LowLevel, CODE, READONLY + +;/** +; +; This allows the caller to switch the stack and goes to the new entry point +; +; @param EntryPoint The pointer to the location to enter +; @param Context Parameter to pass in +; @param Context2 Parameter2 to pass in +; @param NewStack New Location of the stack +; +; @return Nothing. Goes to the Entry Point passing in the new parameters +; +;**/ +;VOID +;EFIAPI +;InternalSwitchStackAsm ( +; SWITCH_STACK_ENTRY_POINT EntryPoint, +; VOID *Context, +; VOID *Context2, +; VOID *NewStack +; ); +; +InternalSwitchStackAsm + mov x29, #0 + mov x30, x0 + mov sp, x3 + mov x0, x1 + mov x1, x2 + ret + +;/** +; +; Requests CPU to pause for a short period of time. +; +; Requests CPU to pause for a short period of time. Typically used in MP +; systems to prevent memory starvation while waiting for a spin lock. +; +;**/ +;VOID +;EFIAPI +;CpuPause ( +; VOID +; ) +; +CpuPause + nop + nop + nop + nop + nop + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/ARShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/ARShiftU64.c new file mode 100644 index 000000000..9928854dd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/ARShiftU64.c @@ -0,0 +1,35 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with the original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathARShiftU64 (Operand, Count); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S new file mode 100644 index 000000000..3bc2246a8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# CpuBreakpoint() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(CpuBreakpoint) + +#/** +# Generates a breakpoint on the CPU. +# +# Generates a breakpoint on the CPU. The breakpoint must be implemented such +# that code can resume normal execution after the breakpoint. +# +#**/ +#VOID +#EFIAPI +#CpuBreakpoint ( +# VOID +# ); +# +ASM_PFX(CpuBreakpoint): + swi 0xdbdbdb + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm new file mode 100644 index 000000000..baf6d2783 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; CpuBreakpoint() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuBreakpoint + +; Force ARM mode for this section, as MSFT assembler defaults to THUMB + AREA Cpu_Breakpoint, CODE, READONLY, ARM + + ARM + +;/** +; Generates a breakpoint on the CPU. +; +; Generates a breakpoint on the CPU. The breakpoint must be implemented such +; that code can resume normal execution after the breakpoint. +; +;**/ +;VOID +;EFIAPI +;CpuBreakpoint ( +; VOID +; ); +; +CpuBreakpoint + swi 0xdbdbdb + bx lr + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm new file mode 100644 index 000000000..a16223c7f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; CpuPause() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT CpuPause + AREA cpu_pause, CODE, READONLY + +;/** +; Requests CPU to pause for a short period of time. +; +; Requests CPU to pause for a short period of time. Typically used in MP +; systems to prevent memory starvation while waiting for a spin lock. +; +;**/ +;VOID +;EFIAPI +;CpuPause ( +; VOID +; ); +; +CpuPause + NOP + NOP + NOP + NOP + NOP + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S new file mode 100644 index 000000000..1f3fe7cc9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S @@ -0,0 +1,29 @@ +#------------------------------------------------------------------------------ +# +# DisableInterrupts() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(DisableInterrupts) + +#/** +# Disables CPU interrupts. +# +#**/ +#VOID +#EFIAPI +#DisableInterrupts ( +# VOID +# ); +# +ASM_PFX(DisableInterrupts): + mrs R0,CPSR + orr R0,R0,#0x80 @Disable IRQ interrupts + msr CPSR_c,R0 + bx LR diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm new file mode 100644 index 000000000..e4e90b5f7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; DisableInterrupts() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT DisableInterrupts + + AREA Interrupt_disable, CODE, READONLY + +;/** +; Disables CPU interrupts. +; +;**/ +;VOID +;EFIAPI +;DisableInterrupts ( +; VOID +; ); +; +DisableInterrupts + MRS R0,CPSR + ORR R0,R0,#0x80 ;Disable IRQ interrupts + MSR CPSR_c,R0 + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S new file mode 100644 index 000000000..5de3b0945 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# EnableInterrupts() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT(EnableInterrupts) + + +#/** +# Enables CPU interrupts. +# +#**/ +#VOID +#EFIAPI +#EnableInterrupts ( +# VOID +# ); +# +ASM_PFX(EnableInterrupts): + mrs R0,CPSR + bic R0,R0,#0x80 @Enable IRQ interrupts + msr CPSR_c,R0 + bx LR diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm new file mode 100644 index 000000000..0fcf66f7d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; EnableInterrupts() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT EnableInterrupts + + AREA Interrupt_enable, CODE, READONLY + +;/** +; Enables CPU interrupts. +; +;**/ +;VOID +;EFIAPI +;EnableInterrupts ( +; VOID +; ); +; +EnableInterrupts + MRS R0,CPSR + BIC R0,R0,#0x80 ;Enable IRQ interrupts + MSR CPSR_c,R0 + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S new file mode 100644 index 000000000..d5ee7d0e2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------ +# +# GetInterruptState() function for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +.text +.p2align 2 +GCC_ASM_EXPORT (GetInterruptState) + +#/** +# Retrieves the current CPU interrupt state. +# +# Returns TRUE is interrupts are currently enabled. Otherwise +# returns FALSE. +# +# @retval TRUE CPU interrupts are enabled. +# @retval FALSE CPU interrupts are disabled. +# +#**/ +# +#BOOLEAN +#EFIAPI +#GetInterruptState ( +# VOID +# ); +# +ASM_PFX(GetInterruptState): + mrs R0, CPSR + tst R0, #0x80 @Check if IRQ is enabled. + moveq R0, #1 + movne R0, #0 + bx LR diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm new file mode 100644 index 000000000..af7b9d6c6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; GetInterruptState() function for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT GetInterruptState + + AREA Interrupt_enable, CODE, READONLY + +;/** +; Retrieves the current CPU interrupt state. +; +; Returns TRUE is interrupts are currently enabled. Otherwise +; returns FALSE. +; +; @retval TRUE CPU interrupts are enabled. +; @retval FALSE CPU interrupts are disabled. +; +;**/ +; +;BOOLEAN +;EFIAPI +;GetInterruptState ( +; VOID +; ); +; +GetInterruptState + MRS R0, CPSR + TST R0, #0x80 ;Check if IRQ is enabled. + MOVEQ R0, #1 + MOVNE R0, #0 + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c b/roms/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c new file mode 100644 index 000000000..3fe1125b6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c @@ -0,0 +1,73 @@ +/** @file + SwitchStack() function for ARM. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Transfers control to a function starting with a new stack. + + This internal worker function transfers control to the function + specified by EntryPoint using the new stack specified by NewStack, + and passes in the parameters specified by Context1 and Context2. + Context1 and Context2 are optional and may be NULL. + The function EntryPoint must never return. + + @param EntryPoint The pointer to the function to enter. + @param Context1 The first parameter to pass in. + @param Context2 The second Parameter to pass in + @param NewStack The new Location of the stack + +**/ +VOID +EFIAPI +InternalSwitchStackAsm ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack, and passes in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. + Marker will be ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param Marker A VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +InternalSwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + IN VA_LIST Marker + ) + +{ + InternalSwitchStackAsm (EntryPoint, Context1, Context2, NewStack); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/Math64.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/Math64.S new file mode 100755 index 000000000..ec12b1015 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/Math64.S @@ -0,0 +1,263 @@ +#------------------------------------------------------------------------------ +# +# Replacement for Math64.c that is coded to use older GCC intrinsics. +# Doing this reduces the number of intrinsics that are required when +# you port to a new version of gcc. +# +# Need to split this into multple files to size optimize the image. +# +# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + + .text + .align 2 + GCC_ASM_EXPORT(InternalMathLShiftU64) + +ASM_PFX(InternalMathLShiftU64): + stmfd sp!, {r4, r5, r6} + mov r6, r1 + rsb ip, r2, #32 + mov r4, r6, asl r2 + subs r1, r2, #32 + orr r4, r4, r0, lsr ip + mov r3, r0, asl r2 + movpl r4, r0, asl r1 + mov r5, r0 + mov r0, r3 + mov r1, r4 + ldmfd sp!, {r4, r5, r6} + bx lr + + .align 2 + GCC_ASM_EXPORT(InternalMathRShiftU64) + +ASM_PFX(InternalMathRShiftU64): + stmfd sp!, {r4, r5, r6} + mov r5, r0 + rsb ip, r2, #32 + mov r3, r5, lsr r2 + subs r0, r2, #32 + orr r3, r3, r1, asl ip + mov r4, r1, lsr r2 + movpl r3, r1, lsr r0 + mov r6, r1 + mov r0, r3 + mov r1, r4 + ldmfd sp!, {r4, r5, r6} + bx lr + + .align 2 + GCC_ASM_EXPORT(InternalMathARShiftU64) + +ASM_PFX(InternalMathARShiftU64): + stmfd sp!, {r4, r5, r6} + mov r5, r0 + rsb ip, r2, #32 + mov r3, r5, lsr r2 + subs r0, r2, #32 + orr r3, r3, r1, asl ip + mov r4, r1, asr r2 + movpl r3, r1, asr r0 + mov r6, r1 + mov r0, r3 + mov r1, r4 + ldmfd sp!, {r4, r5, r6} + bx lr + + .align 2 + GCC_ASM_EXPORT(InternalMathLRotU64) + +ASM_PFX(InternalMathLRotU64): + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + mov r6, r1 + rsb ip, r2, #32 + mov r4, r6, asl r2 + rsb lr, r2, #64 + subs r1, r2, #32 + orr r4, r4, r0, lsr ip + mov r3, r0, asl r2 + movpl r4, r0, asl r1 + sub ip, r2, #32 + mov r5, r0 + mov r0, r0, lsr lr + rsbs r2, r2, #32 + orr r0, r0, r6, asl ip + mov r1, r6, lsr lr + movpl r0, r6, lsr r2 + orr r1, r1, r4 + orr r0, r0, r3 + ldmfd sp!, {r4, r5, r6, r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathRRotU64) + +ASM_PFX(InternalMathRRotU64): + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + mov r5, r0 + rsb ip, r2, #32 + mov r3, r5, lsr r2 + rsb lr, r2, #64 + subs r0, r2, #32 + orr r3, r3, r1, asl ip + mov r4, r1, lsr r2 + movpl r3, r1, lsr r0 + sub ip, r2, #32 + mov r6, r1 + mov r1, r1, asl lr + rsbs r2, r2, #32 + orr r1, r1, r5, lsr ip + mov r0, r5, asl lr + movpl r1, r5, asl r2 + orr r0, r0, r3 + orr r1, r1, r4 + ldmfd sp!, {r4, r5, r6, r7, pc} + + .align 2 + GCC_ASM_EXPORT(InternalMathMultU64x32) + +ASM_PFX(InternalMathMultU64x32): + stmfd sp!, {r7, lr} + add r7, sp, #0 + mov r3, #0 + mov ip, r0 + mov lr, r1 + umull r0, r1, ip, r2 + mla r1, lr, r2, r1 + mla r1, ip, r3, r1 + ldmfd sp!, {r7, pc} + + .align 2 + GCC_ASM_EXPORT(InternalMathMultU64x64) + +ASM_PFX(InternalMathMultU64x64): + stmfd sp!, {r7, lr} + add r7, sp, #0 + mov ip, r0 + mov lr, r1 + umull r0, r1, ip, r2 + mla r1, lr, r2, r1 + mla r1, ip, r3, r1 + ldmfd sp!, {r7, pc} + + .align 2 + GCC_ASM_EXPORT(InternalMathDivU64x32) + +ASM_PFX(InternalMathDivU64x32): + stmfd sp!, {r7, lr} + add r7, sp, #0 + mov r3, #0 + bl ASM_PFX(__udivdi3) + ldmfd sp!, {r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathModU64x32) + +ASM_PFX(InternalMathModU64x32): + stmfd sp!, {r7, lr} + add r7, sp, #0 + mov r3, #0 + bl ASM_PFX(__umoddi3) + ldmfd sp!, {r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathDivRemU64x32) + +ASM_PFX(InternalMathDivRemU64x32): + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r10, r11} + subs r6, r3, #0 + mov r10, r0 + mov r11, r1 + moveq r4, r2 + moveq r5, #0 + beq L22 + mov r4, r2 + mov r5, #0 + mov r3, #0 + bl ASM_PFX(__umoddi3) + str r0, [r6, #0] +L22: + mov r0, r10 + mov r1, r11 + mov r2, r4 + mov r3, r5 + bl ASM_PFX(__udivdi3) + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathDivRemU64x64) + +ASM_PFX(InternalMathDivRemU64x64): + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r10, r11} + ldr r6, [sp, #28] + mov r4, r0 + cmp r6, #0 + mov r5, r1 + mov r10, r2 + mov r11, r3 + beq L26 + bl ASM_PFX(__umoddi3) + stmia r6, {r0-r1} +L26: + mov r0, r4 + mov r1, r5 + mov r2, r10 + mov r3, r11 + bl ASM_PFX(__udivdi3) + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathDivRemS64x64) + +ASM_PFX(InternalMathDivRemS64x64): + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r10, r11} + ldr r6, [sp, #28] + mov r4, r0 + cmp r6, #0 + mov r5, r1 + mov r10, r2 + mov r11, r3 + beq L30 + bl ASM_PFX(__moddi3) + stmia r6, {r0-r1} +L30: + mov r0, r4 + mov r1, r5 + mov r2, r10 + mov r3, r11 + bl ASM_PFX(__divdi3) + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} + + + .align 2 + GCC_ASM_EXPORT(InternalMathSwapBytes64) + +ASM_PFX(InternalMathSwapBytes64): + stmfd sp!, {r4, r5, r7, lr} + mov r5, r1 + bl ASM_PFX(SwapBytes32) + mov r4, r0 + mov r0, r5 + bl ASM_PFX(SwapBytes32) + mov r1, r4 + ldmfd sp!, {r4, r5, r7, pc} + + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S new file mode 100644 index 000000000..8bf1a7505 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S @@ -0,0 +1,33 @@ +##------------------------------------------------------------------------------ +# +# MemoryFence() for AArch64 +# +# Copyright (c) 2013, ARM Ltd. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +##------------------------------------------------------------------------------ + +.text +.p2align 2 + +GCC_ASM_EXPORT(MemoryFence) + + +#/** +# Used to serialize load and store operations. +# +# All loads and stores that proceed calls to this function are guaranteed to be +# globally visible when this function returns. +# +#**/ +#VOID +#EFIAPI +#MemoryFence ( +# VOID +# ); +# +ASM_PFX(MemoryFence): + // System wide Data Memory Barrier. + dmb + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm new file mode 100644 index 000000000..e751584aa --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; MemoryFence() for AArch64 +; +; Copyright (c) 2013, ARM Ltd. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT MemoryFence + + AREA MemoryBarriers, CODE, READONLY + +;/** +; Used to serialize load and store operations. +; +; All loads and stores that proceed calls to this function are guaranteed to be +; globally visible when this function returns. +; +;**/ +;VOID +;EFIAPI +;MemoryFence ( +; VOID +; ); +; +MemoryFence FUNCTION + dmb + bx lr + ENDFUNC + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S new file mode 100644 index 000000000..82d94faf6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S @@ -0,0 +1,64 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ +.text +.p2align 2 + +GCC_ASM_EXPORT(SetJump) +GCC_ASM_EXPORT(InternalLongJump) + +#/** +# Saves the current CPU context that can be restored with a call to LongJump() and returns 0.# +# +# Saves the current CPU context in the buffer specified by JumpBuffer and returns 0. The initial +# call to SetJump() must always return 0. Subsequent calls to LongJump() cause a non-zero +# value to be returned by SetJump(). +# +# If JumpBuffer is NULL, then ASSERT(). +# For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). +# +# @param JumpBuffer A pointer to CPU context buffer. +# +#**/ +# +#UINTN +#EFIAPI +#SetJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer // R0 +# ); +# +ASM_PFX(SetJump): + mov r3, r13 + stmia r0, {r3-r12,r14} + eor r0, r0, r0 + bx lr + +#/** +# Restores the CPU context that was saved with SetJump().# +# +# Restores the CPU context from the buffer specified by JumpBuffer. +# This function never returns to the caller. +# Instead is resumes execution based on the state of JumpBuffer. +# +# @param JumpBuffer A pointer to CPU context buffer. +# @param Value The value to return when the SetJump() context is restored. +# +#**/ +#VOID +#EFIAPI +#InternalLongJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, // R0 +# IN UINTN Value // R1 +# ); +# +ASM_PFX(InternalLongJump): + ldmia r0, {r3-r12,r14} + mov r13, r3 + mov r0, r1 + bx lr + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm new file mode 100644 index 000000000..936f722be --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm @@ -0,0 +1,64 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT SetJump + EXPORT InternalLongJump + + AREA BaseLib, CODE, READONLY + +;/** +; Saves the current CPU context that can be restored with a call to LongJump() and returns 0.; +; +; Saves the current CPU context in the buffer specified by JumpBuffer and returns 0. The initial +; call to SetJump() must always return 0. Subsequent calls to LongJump() cause a non-zero +; value to be returned by SetJump(). +; +; If JumpBuffer is NULL, then ASSERT(). +; For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). +; +; @param JumpBuffer A pointer to CPU context buffer. +; +;**/ +; +;UINTN +;EFIAPI +;SetJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer // R0 +; ) +; +SetJump + MOV R3, R13 + STM R0, {R3-R12,R14} + EOR R0, R0 + BX LR + +;/** +; Restores the CPU context that was saved with SetJump().; +; +; Restores the CPU context from the buffer specified by JumpBuffer. +; This function never returns to the caller. +; Instead is resumes execution based on the state of JumpBuffer. +; +; @param JumpBuffer A pointer to CPU context buffer. +; @param Value The value to return when the SetJump() context is restored. +; +;**/ +;VOID +;EFIAPI +;InternalLongJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, // R0 +; IN UINTN Value // R1 +; ); +; +InternalLongJump + LDM R0, {R3-R12,R14} + MOV R13, R3 + MOV R0, R1 + BX LR + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S new file mode 100644 index 000000000..73f8105e3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S @@ -0,0 +1,33 @@ +##------------------------------------------------------------------------------ +# +# SpeculationBarrier() for AArch64 +# +# Copyright (c) 2019, Linaro Ltd. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +##------------------------------------------------------------------------------ + +.text +.p2align 2 + +GCC_ASM_EXPORT(SpeculationBarrier) + + +#/** +# Uses as a barrier to stop speculative execution. +# +# Ensures that no later instruction will execute speculatively, until all prior +# instructions have completed. +# +#**/ +#VOID +#EFIAPI +#SpeculationBarrier ( +# VOID +# ); +# +ASM_PFX(SpeculationBarrier): + dsb + isb + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm new file mode 100644 index 000000000..01a64346f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; SpeculationBarrier() for AArch64 +; +; Copyright (c) 2019, Linaro Ltd. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT SpeculationBarrier + + AREA MemoryBarriers, CODE, READONLY + +;/** +; Uses as a barrier to stop speculative execution. +; +; Ensures that no later instruction will execute speculatively, until all prior +; instructions have completed. +; +;**/ +;VOID +;EFIAPI +;SpeculationBarrier ( +; VOID +; ); +; +SpeculationBarrier + dsb + isb + bx lr + + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S b/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S new file mode 100644 index 000000000..844c9a27f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// Portions copyright (c) 2011, ARM Limited. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ + +.text +.align 5 + +GCC_ASM_EXPORT(InternalSwitchStackAsm) +GCC_ASM_EXPORT(CpuPause) + +/** +// +// This allows the caller to switch the stack and goes to the new entry point +// +// @param EntryPoint The pointer to the location to enter +// @param Context Parameter to pass in +// @param Context2 Parameter2 to pass in +// @param NewStack New Location of the stack +// +// @return Nothing. Goes to the Entry Point passing in the new parameters +// +VOID +EFIAPI +InternalSwitchStackAsm ( + SWITCH_STACK_ENTRY_POINT EntryPoint, + VOID *Context, + VOID *Context2, + VOID *NewStack + ); +**/ +ASM_PFX(InternalSwitchStackAsm): + MOV LR, R0 + MOV SP, R3 + MOV R0, R1 + MOV R1, R2 + BX LR + +/** +// +// Requests CPU to pause for a short period of time. +// +// Requests CPU to pause for a short period of time. Typically used in MP +// systems to prevent memory starvation while waiting for a spin lock. +// +VOID +EFIAPI +CpuPause ( + VOID + ) +**/ +ASM_PFX(CpuPause): + nop + nop + nop + nop + nop + BX LR diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm b/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm new file mode 100644 index 000000000..690f632e6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT InternalSwitchStackAsm + + AREA Switch_Stack, CODE, READONLY + +;/** +; This allows the caller to switch the stack and goes to the new entry point +; +; @param EntryPoint The pointer to the location to enter +; @param Context Parameter to pass in +; @param Context2 Parameter2 to pass in +; @param NewStack New Location of the stack +; +; @return Nothing. Goes to the Entry Point passing in the new parameters +; +;**/ +;VOID +;EFIAPI +;InternalSwitchStackAsm ( +; SWITCH_STACK_ENTRY_POINT EntryPoint, +; VOID *Context, +; VOID *Context2, +; VOID *NewStack +; ); +; +InternalSwitchStackAsm + MOV LR, R0 + MOV SP, R3 + MOV R0, R1 + MOV R1, R2 + BX LR + END diff --git a/roms/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c b/roms/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c new file mode 100644 index 000000000..e9934e700 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c @@ -0,0 +1,246 @@ +/** @file + Unaligned access functions of BaseLib for ARM. + + volatile was added to work around optimization issues. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + + @return The 16-bit value read from Buffer. + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ) +{ + volatile UINT8 LowerByte; + volatile UINT8 HigherByte; + + ASSERT (Buffer != NULL); + + LowerByte = ((UINT8*)Buffer)[0]; + HigherByte = ((UINT8*)Buffer)[1]; + + return (UINT16)(LowerByte | (HigherByte << 8)); +} + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return The 16-bit value to write to Buffer. + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + + ((volatile UINT8*)Buffer)[0] = (UINT8)Value; + ((volatile UINT8*)Buffer)[1] = (UINT8)(Value >> 8); + + return Value; +} + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + + @return The 24-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return (UINT32)( + ReadUnaligned16 ((UINT16*)Buffer) | + (((UINT8*)Buffer)[2] << 16) + ); +} + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The 24-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); + *(UINT8*)((UINT16*)Buffer + 1) = (UINT8)(Value >> 16); + return Value; +} + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + + @return The 32-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ) +{ + UINT16 LowerBytes; + UINT16 HigherBytes; + + ASSERT (Buffer != NULL); + + LowerBytes = ReadUnaligned16 ((UINT16*) Buffer); + HigherBytes = ReadUnaligned16 ((UINT16*) Buffer + 1); + + return (UINT32) (LowerBytes | (HigherBytes << 16)); +} + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return The 32-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); + WriteUnaligned16 ((UINT16*)Buffer + 1, (UINT16)(Value >> 16)); + return Value; +} + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + + @return The 64-bit value read from Buffer. + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ) +{ + UINT32 LowerBytes; + UINT32 HigherBytes; + + ASSERT (Buffer != NULL); + + LowerBytes = ReadUnaligned32 ((UINT32*) Buffer); + HigherBytes = ReadUnaligned32 ((UINT32*) Buffer + 1); + + return (UINT64) (LowerBytes | LShiftU64 (HigherBytes, 32)); +} + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return The 64-bit value to write to Buffer. + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + + WriteUnaligned32 ((UINT32*)Buffer, (UINT32)Value); + WriteUnaligned32 ((UINT32*)Buffer + 1, (UINT32)RShiftU64 (Value, 32)); + return Value; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/BaseLib.inf b/roms/edk2/MdePkg/Library/BaseLib/BaseLib.inf new file mode 100644 index 000000000..3b85c56c3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/BaseLib.inf @@ -0,0 +1,422 @@ +## @file +# Base Library implementation. +# +# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseLib + MODULE_UNI_FILE = BaseLib.uni + FILE_GUID = 27d67720-ea68-48ae-93da-a3a074c90e30 + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = BaseLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources] + CheckSum.c + SwitchStack.c + SwapBytes64.c + SwapBytes32.c + SwapBytes16.c + LongJump.c + SetJump.c + RShiftU64.c + RRotU64.c + RRotU32.c + MultU64x64.c + MultU64x32.c + MultS64x64.c + ModU64x32.c + LShiftU64.c + LRotU64.c + LRotU32.c + LowBitSet64.c + LowBitSet32.c + HighBitSet64.c + HighBitSet32.c + GetPowerOfTwo64.c + GetPowerOfTwo32.c + DivU64x64Remainder.c + DivU64x32Remainder.c + DivU64x32.c + DivS64x64Remainder.c + ARShiftU64.c + BitField.c + CpuDeadLoop.c + Cpu.c + LinkedList.c + SafeString.c + String.c + FilePaths.c + BaseLibInternals.h + +[Sources.Ia32] + Ia32/WriteTr.nasm + Ia32/Lfence.nasm + + Ia32/Wbinvd.c | MSFT + Ia32/WriteMm7.c | MSFT + Ia32/WriteMm6.c | MSFT + Ia32/WriteMm5.c | MSFT + Ia32/WriteMm4.c | MSFT + Ia32/WriteMm3.c | MSFT + Ia32/WriteMm2.c | MSFT + Ia32/WriteMm1.c | MSFT + Ia32/WriteMm0.c | MSFT + Ia32/WriteLdtr.c | MSFT + Ia32/WriteIdtr.c | MSFT + Ia32/WriteGdtr.c | MSFT + Ia32/WriteDr7.c | MSFT + Ia32/WriteDr6.c | MSFT + Ia32/WriteDr5.c | MSFT + Ia32/WriteDr4.c | MSFT + Ia32/WriteDr3.c | MSFT + Ia32/WriteDr2.c | MSFT + Ia32/WriteDr1.c | MSFT + Ia32/WriteDr0.c | MSFT + Ia32/WriteCr4.c | MSFT + Ia32/WriteCr3.c | MSFT + Ia32/WriteCr2.c | MSFT + Ia32/WriteCr0.c | MSFT + Ia32/WriteMsr64.c | MSFT + Ia32/SwapBytes64.c | MSFT + Ia32/RRotU64.c | MSFT + Ia32/RShiftU64.c | MSFT + Ia32/ReadPmc.c | MSFT + Ia32/ReadTsc.c | MSFT + Ia32/ReadLdtr.c | MSFT + Ia32/ReadIdtr.c | MSFT + Ia32/ReadGdtr.c | MSFT + Ia32/ReadTr.c | MSFT + Ia32/ReadSs.c | MSFT + Ia32/ReadGs.c | MSFT + Ia32/ReadFs.c | MSFT + Ia32/ReadEs.c | MSFT + Ia32/ReadDs.c | MSFT + Ia32/ReadCs.c | MSFT + Ia32/ReadMsr64.c | MSFT + Ia32/ReadMm7.c | MSFT + Ia32/ReadMm6.c | MSFT + Ia32/ReadMm5.c | MSFT + Ia32/ReadMm4.c | MSFT + Ia32/ReadMm3.c | MSFT + Ia32/ReadMm2.c | MSFT + Ia32/ReadMm1.c | MSFT + Ia32/ReadMm0.c | MSFT + Ia32/ReadEflags.c | MSFT + Ia32/ReadDr7.c | MSFT + Ia32/ReadDr6.c | MSFT + Ia32/ReadDr5.c | MSFT + Ia32/ReadDr4.c | MSFT + Ia32/ReadDr3.c | MSFT + Ia32/ReadDr2.c | MSFT + Ia32/ReadDr1.c | MSFT + Ia32/ReadDr0.c | MSFT + Ia32/ReadCr4.c | MSFT + Ia32/ReadCr3.c | MSFT + Ia32/ReadCr2.c | MSFT + Ia32/ReadCr0.c | MSFT + Ia32/Mwait.c | MSFT + Ia32/Monitor.c | MSFT + Ia32/ModU64x32.c | MSFT + Ia32/MultU64x64.c | MSFT + Ia32/MultU64x32.c | MSFT + Ia32/LShiftU64.c | MSFT + Ia32/LRotU64.c | MSFT + Ia32/Invd.c | MSFT + Ia32/FxRestore.c | MSFT + Ia32/FxSave.c | MSFT + Ia32/FlushCacheLine.c | MSFT + Ia32/EnablePaging32.c | MSFT + Ia32/EnableInterrupts.c | MSFT + Ia32/EnableDisableInterrupts.c | MSFT + Ia32/DivU64x32Remainder.c | MSFT + Ia32/DivU64x32.c | MSFT + Ia32/DisablePaging32.c | MSFT + Ia32/DisableInterrupts.c | MSFT + Ia32/CpuPause.c | MSFT + Ia32/CpuIdEx.c | MSFT + Ia32/CpuId.c | MSFT + Ia32/CpuBreakpoint.c | MSFT + Ia32/ARShiftU64.c | MSFT + Ia32/EnableCache.c | MSFT + Ia32/DisableCache.c | MSFT + + + Ia32/GccInline.c | GCC + Ia32/GccInlinePriv.c | GCC + Ia32/Thunk16.nasm + Ia32/EnableDisableInterrupts.nasm| GCC + Ia32/EnablePaging64.nasm + Ia32/DisablePaging32.nasm| GCC + Ia32/EnablePaging32.nasm| GCC + Ia32/Mwait.nasm| GCC + Ia32/Monitor.nasm| GCC + Ia32/CpuIdEx.nasm| GCC + Ia32/CpuId.nasm| GCC + Ia32/LongJump.nasm + Ia32/SetJump.nasm + Ia32/SwapBytes64.nasm| GCC + Ia32/DivU64x64Remainder.nasm + Ia32/DivU64x32Remainder.nasm| GCC + Ia32/ModU64x32.nasm| GCC + Ia32/DivU64x32.nasm| GCC + Ia32/MultU64x64.nasm| GCC + Ia32/MultU64x32.nasm| GCC + Ia32/RRotU64.nasm| GCC + Ia32/LRotU64.nasm| GCC + Ia32/ARShiftU64.nasm| GCC + Ia32/RShiftU64.nasm| GCC + Ia32/LShiftU64.nasm| GCC + Ia32/EnableCache.nasm| GCC + Ia32/DisableCache.nasm| GCC + Ia32/RdRand.nasm + Ia32/XGetBv.nasm + Ia32/VmgExit.nasm + + Ia32/DivS64x64Remainder.c + Ia32/InternalSwitchStack.c | MSFT + Ia32/InternalSwitchStack.nasm | GCC + Ia32/Non-existing.c + Unaligned.c + X86WriteIdtr.c + X86WriteGdtr.c + X86Thunk.c + X86ReadIdtr.c + X86ReadGdtr.c + X86Msr.c + X86MemoryFence.c | MSFT + X86GetInterruptState.c + X86FxSave.c + X86FxRestore.c + X86EnablePaging64.c + X86EnablePaging32.c + X86DisablePaging64.c + X86DisablePaging32.c + X86RdRand.c + X86PatchInstruction.c + X86SpeculationBarrier.c + +[Sources.X64] + X64/Thunk16.nasm + X64/CpuIdEx.nasm + X64/CpuId.nasm + X64/LongJump.nasm + X64/SetJump.nasm + X64/SwitchStack.nasm + X64/EnableCache.nasm + X64/DisableCache.nasm + X64/WriteTr.nasm + X64/Lfence.nasm + + X64/CpuBreakpoint.c | MSFT + X64/WriteMsr64.c | MSFT + X64/ReadMsr64.c | MSFT + X64/CpuPause.nasm| MSFT + X64/DisableInterrupts.nasm| MSFT + X64/EnableInterrupts.nasm| MSFT + X64/FlushCacheLine.nasm| MSFT + X64/Invd.nasm| MSFT + X64/Wbinvd.nasm| MSFT + X64/Mwait.nasm| MSFT + X64/Monitor.nasm| MSFT + X64/ReadPmc.nasm| MSFT + X64/ReadTsc.nasm| MSFT + X64/WriteMm7.nasm| MSFT + X64/WriteMm6.nasm| MSFT + X64/WriteMm5.nasm| MSFT + X64/WriteMm4.nasm| MSFT + X64/WriteMm3.nasm| MSFT + X64/WriteMm2.nasm| MSFT + X64/WriteMm1.nasm| MSFT + X64/WriteMm0.nasm| MSFT + X64/ReadMm7.nasm| MSFT + X64/ReadMm6.nasm| MSFT + X64/ReadMm5.nasm| MSFT + X64/ReadMm4.nasm| MSFT + X64/ReadMm3.nasm| MSFT + X64/ReadMm2.nasm| MSFT + X64/ReadMm1.nasm| MSFT + X64/ReadMm0.nasm| MSFT + X64/FxRestore.nasm| MSFT + X64/FxSave.nasm| MSFT + X64/WriteLdtr.nasm| MSFT + X64/ReadLdtr.nasm| MSFT + X64/WriteIdtr.nasm| MSFT + X64/ReadIdtr.nasm| MSFT + X64/WriteGdtr.nasm| MSFT + X64/ReadGdtr.nasm| MSFT + X64/ReadTr.nasm| MSFT + X64/ReadSs.nasm| MSFT + X64/ReadGs.nasm| MSFT + X64/ReadFs.nasm| MSFT + X64/ReadEs.nasm| MSFT + X64/ReadDs.nasm| MSFT + X64/ReadCs.nasm| MSFT + X64/WriteDr7.nasm| MSFT + X64/WriteDr6.nasm| MSFT + X64/WriteDr5.nasm| MSFT + X64/WriteDr4.nasm| MSFT + X64/WriteDr3.nasm| MSFT + X64/WriteDr2.nasm| MSFT + X64/WriteDr1.nasm| MSFT + X64/WriteDr0.nasm| MSFT + X64/ReadDr7.nasm| MSFT + X64/ReadDr6.nasm| MSFT + X64/ReadDr5.nasm| MSFT + X64/ReadDr4.nasm| MSFT + X64/ReadDr3.nasm| MSFT + X64/ReadDr2.nasm| MSFT + X64/ReadDr1.nasm| MSFT + X64/ReadDr0.nasm| MSFT + X64/WriteCr4.nasm| MSFT + X64/WriteCr3.nasm| MSFT + X64/WriteCr2.nasm| MSFT + X64/WriteCr0.nasm| MSFT + X64/ReadCr4.nasm| MSFT + X64/ReadCr3.nasm| MSFT + X64/ReadCr2.nasm| MSFT + X64/ReadCr0.nasm| MSFT + X64/ReadEflags.nasm| MSFT + + + X64/Non-existing.c + Math64.c + Unaligned.c + X86WriteIdtr.c + X86WriteGdtr.c + X86Thunk.c + X86ReadIdtr.c + X86ReadGdtr.c + X86Msr.c + X86MemoryFence.c | MSFT + X86GetInterruptState.c + X86FxSave.c + X86FxRestore.c + X86EnablePaging64.c + X86EnablePaging32.c + X86DisablePaging64.c + X86DisablePaging32.c + X86RdRand.c + X86PatchInstruction.c + X86SpeculationBarrier.c + X64/GccInline.c | GCC + X64/GccInlinePriv.c | GCC + X64/EnableDisableInterrupts.nasm + X64/DisablePaging64.nasm + X64/RdRand.nasm + X64/XGetBv.nasm + X64/VmgExit.nasm + ChkStkGcc.c | GCC + +[Sources.EBC] + Ebc/CpuBreakpoint.c + Ebc/SetJumpLongJump.c + Ebc/SwitchStack.c + Ebc/SpeculationBarrier.c + Unaligned.c + Math64.c + +[Sources.ARM] + Arm/InternalSwitchStack.c + Arm/Unaligned.c + Math64.c | RVCT + Math64.c | MSFT + + Arm/SwitchStack.asm | RVCT + Arm/SetJumpLongJump.asm | RVCT + Arm/DisableInterrupts.asm | RVCT + Arm/EnableInterrupts.asm | RVCT + Arm/GetInterruptsState.asm | RVCT + Arm/CpuPause.asm | RVCT + Arm/CpuBreakpoint.asm | RVCT + Arm/MemoryFence.asm | RVCT + Arm/SpeculationBarrier.S | RVCT + + Arm/SwitchStack.asm | MSFT + Arm/SetJumpLongJump.asm | MSFT + Arm/DisableInterrupts.asm | MSFT + Arm/EnableInterrupts.asm | MSFT + Arm/GetInterruptsState.asm | MSFT + Arm/CpuPause.asm | MSFT + Arm/CpuBreakpoint.asm | MSFT + Arm/MemoryFence.asm | MSFT + Arm/SpeculationBarrier.asm | MSFT + + Arm/Math64.S | GCC + Arm/SwitchStack.S | GCC + Arm/EnableInterrupts.S | GCC + Arm/DisableInterrupts.S | GCC + Arm/GetInterruptsState.S | GCC + Arm/SetJumpLongJump.S | GCC + Arm/CpuBreakpoint.S | GCC + Arm/MemoryFence.S | GCC + Arm/SpeculationBarrier.S | GCC + +[Sources.AARCH64] + Arm/InternalSwitchStack.c + Arm/Unaligned.c + Math64.c + + AArch64/MemoryFence.S | GCC + AArch64/SwitchStack.S | GCC + AArch64/EnableInterrupts.S | GCC + AArch64/DisableInterrupts.S | GCC + AArch64/GetInterruptsState.S | GCC + AArch64/SetJumpLongJump.S | GCC + AArch64/CpuBreakpoint.S | GCC + AArch64/SpeculationBarrier.S | GCC + + AArch64/MemoryFence.asm | MSFT + AArch64/SwitchStack.asm | MSFT + AArch64/EnableInterrupts.asm | MSFT + AArch64/DisableInterrupts.asm | MSFT + AArch64/GetInterruptsState.asm | MSFT + AArch64/SetJumpLongJump.asm | MSFT + AArch64/CpuBreakpoint.asm | MSFT + AArch64/SpeculationBarrier.asm | MSFT + +[Sources.RISCV64] + Math64.c + Unaligned.c + RiscV64/InternalSwitchStack.c + RiscV64/CpuBreakpoint.c + RiscV64/GetInterruptState.c + RiscV64/DisableInterrupts.c + RiscV64/EnableInterrupts.c + RiscV64/CpuPause.c + RiscV64/RiscVSetJumpLongJump.S | GCC + RiscV64/RiscVCpuBreakpoint.S | GCC + RiscV64/RiscVCpuPause.S | GCC + RiscV64/RiscVInterrupt.S | GCC + RiscV64/FlushCache.S | GCC + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + DebugLib + BaseMemoryLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdSpeculationBarrierType ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/BaseLib/BaseLib.uni b/roms/edk2/MdePkg/Library/BaseLib/BaseLib.uni new file mode 100644 index 000000000..3a1b2e744 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/BaseLib.uni @@ -0,0 +1,18 @@ +// /** @file +// Base Library implementation. +// +// Base Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Base Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Library implementation." + diff --git a/roms/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h b/roms/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h new file mode 100644 index 000000000..6837d67d9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -0,0 +1,869 @@ +/** @file + Declaration of internal functions in BaseLib. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_LIB_INTERNALS__ +#define __BASE_LIB_INTERNALS__ + +#include +#include +#include +#include +#include + +// +// Math functions +// + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits + are filled with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand arithmetically shifted right by Count + +**/ +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling + the low bits with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are filled with the high Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling + the high bits with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are filled with the low Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swapped Operand. + +**/ +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ); + +/** + Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor + +**/ +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and + generates a 64-bit signed result and an optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit + signed value Divisor and generates a 64-bit signed quotient. If Remainder + is not NULL, then the 64-bit signed remainder is returned in Remainder. + This function returns the 64-bit signed quotient. + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ); + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. + Marker will be ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param Marker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +InternalSwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + IN VA_LIST Marker + ); + + +/** + Worker function that returns a bit field from Operand. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + + @return The bit field read. + +**/ +UINTN +EFIAPI +BitFieldReadUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Worker function that reads a bit field from Operand, performs a bitwise OR, + and returns the result. + + Performs a bitwise OR between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param OrData The value to OR with the read value from the value + + @return The new value. + +**/ +UINTN +EFIAPI +BitFieldOrUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN OrData + ); + + +/** + Worker function that reads a bit field from Operand, performs a bitwise AND, + and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param AndData The value to And with the read value from the value + + @return The new value. + +**/ +UINTN +EFIAPI +BitFieldAndUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN AndData + ); + + +/** + Worker function that checks ASSERT condition for JumpBuffer + + Checks ASSERT condition for JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + +**/ +VOID +EFIAPI +InternalAssertJumpBuffer ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ); + + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. + This function never returns to the caller. + Instead is resumes execution based on the state of JumpBuffer. + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is restored. + +**/ +VOID +EFIAPI +InternalLongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ); + + +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + L'0' to L'9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsDecimalDigitCharacter ( + IN CHAR16 Char + ); + + +/** + Convert a Unicode character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other + Unicode character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalHexCharToUintn ( + IN CHAR16 Char + ); + + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ); + + +/** + Check if a ASCII character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + '0' to '9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsDecimalDigitCharacter ( + IN CHAR8 Char + ); + + +/** + Check if a ASCII character is a hexadecimal character. + + This internal function checks if a ASCII character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsHexaDecimalDigitCharacter ( + IN CHAR8 Char + ); + + +/** + Convert a ASCII character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + '0' to '9', 'a' to 'f' or 'A' to 'F'. For other + ASCII character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalAsciiHexCharToUintn ( + IN CHAR8 Char + ); + + +// +// Ia32 and x64 specific functions +// +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ); + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ); + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + @param Idtr The pointer to an IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ); + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + @param Idtr The pointer to an IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ); + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and x64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ); + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and x64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +InternalX86EnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +InternalX86DisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +InternalX86EnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ); + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +InternalX86DisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ); + +/** + Generates a 16-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + + **/ +BOOLEAN +EFIAPI +InternalX86RdRand16 ( + OUT UINT16 *Rand + ); + +/** + Generates a 32-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand32 ( + OUT UINT32 *Rand + ); + +/** + Generates a 64-bit random number through RDRAND instruction. + + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand64 ( + OUT UINT64 *Rand + ); + +#else + +#endif + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseLib/BitField.c b/roms/edk2/MdePkg/Library/BaseLib/BitField.c new file mode 100644 index 000000000..0f48a036b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/BitField.c @@ -0,0 +1,1002 @@ +/** @file + Bit field functions of BaseLib. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Worker function that returns a bit field from Operand. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + + @return The bit field read. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldReadUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return (Operand & ~((UINTN)-2 << EndBit)) >> StartBit; +} + +/** + Worker function that reads a bit field from Operand, performs a bitwise OR, + and returns the result. + + Performs a bitwise OR between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param OrData The value to OR with the read value from the value. + + @return The new value. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldOrUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN OrData + ) +{ + // + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT ((OrData >> (EndBit - StartBit)) == ((OrData >> (EndBit - StartBit)) & 1)); + + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand | ((OrData << StartBit) & ~((UINTN) -2 << EndBit)); +} + +/** + Worker function that reads a bit field from Operand, performs a bitwise AND, + and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param AndData The value to And with the read value from the value. + + @return The new value. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldAndUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN AndData + ) +{ + // + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT ((AndData >> (EndBit - StartBit)) == ((AndData >> (EndBit - StartBit)) & 1)); + + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand & ~((~AndData << StartBit) & ~((UINTN)-2 << EndBit)); +} + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr8 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr8 ( + BitFieldAnd8 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr16 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return BitFieldOr16 ( + BitFieldAnd16 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr32 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return BitFieldOr32 ( + BitFieldAnd32 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return RShiftU64 (Operand & ~LShiftU64 ((UINT64)-2, EndBit), StartBit); +} + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr64 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + UINT64 Value1; + UINT64 Value2; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + // + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the result right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (OrData, EndBit - StartBit) == (RShiftU64 (OrData, EndBit - StartBit) & 1)); + + Value1 = LShiftU64 (OrData, StartBit); + Value2 = LShiftU64 ((UINT64) - 2, EndBit); + + return Operand | (Value1 & ~Value2); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + UINT64 Value1; + UINT64 Value2; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + // + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (AndData, EndBit - StartBit) == (RShiftU64 (AndData, EndBit - StartBit) & 1)); + + Value1 = LShiftU64 (~AndData, StartBit); + Value2 = LShiftU64 ((UINT64)-2, EndBit); + + return Operand & ~(Value1 & ~Value2); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return BitFieldOr64 ( + BitFieldAnd64 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field from a 32-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT32 Count; + + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + + Count = BitFieldRead32 (Operand, StartBit, EndBit); + Count -= ((Count >> 1) & 0x55555555); + Count = (Count & 0x33333333) + ((Count >> 2) & 0x33333333); + Count += Count >> 4; + Count &= 0x0F0F0F0F; + Count += Count >> 8; + Count += Count >> 16; + + return (UINT8) Count & 0x3F; +} + +/** + Reads a bit field from a 64-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT64 BitField; + UINT8 Count; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + + BitField = BitFieldRead64 (Operand, StartBit, EndBit); + Count = BitFieldCountOnes32 ((UINT32) BitField, 0, 31); + Count += BitFieldCountOnes32 ((UINT32) RShiftU64(BitField, 32), 0, 31); + + return Count; +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/CheckSum.c b/roms/edk2/MdePkg/Library/BaseLib/CheckSum.c new file mode 100644 index 000000000..d91a7a07c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/CheckSum.c @@ -0,0 +1,626 @@ +/** @file + Utility functions to generate checksum based on 2's complement + algorithm. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the sum of all elements in a buffer in unit of UINT8. + During calculation, the carry bits are dropped. + + This function calculates the sum of all elements in a buffer + in unit of UINT8. The carry bits in result of addition are dropped. + The result is returned as UINT8. If Length is Zero, then Zero is + returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT8 +EFIAPI +CalculateSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ) +{ + UINT8 Sum; + UINTN Count; + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + for (Sum = 0, Count = 0; Count < Length; Count++) { + Sum = (UINT8) (Sum + *(Buffer + Count)); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer + of 8-bit values. + + This function first calculates the sum of the 8-bit values in the + buffer specified by Buffer and Length. The carry bits in the result + of addition are dropped. Then, the two's complement of the sum is + returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT8 +EFIAPI +CalculateCheckSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ) +{ + UINT8 CheckSum; + + CheckSum = CalculateSum8 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT8) (0x100 - CheckSum); +} + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 16-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT16 +EFIAPI +CalculateSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT16 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x1) == 0); + ASSERT ((Length & 0x1) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = (UINT16) (Sum + *(Buffer + Count)); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 16-bit values. + + This function first calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT16 +EFIAPI +CalculateCheckSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT16 CheckSum; + + CheckSum = CalculateSum16 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT16) (0x10000 - CheckSum); +} + + +/** + Returns the sum of all elements in a buffer of 32-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 32-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT32 +EFIAPI +CalculateSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ) +{ + UINT32 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x3) == 0); + ASSERT ((Length & 0x3) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = Sum + *(Buffer + Count); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 32-bit values. + + This function first calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT32 +EFIAPI +CalculateCheckSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ) +{ + UINT32 CheckSum; + + CheckSum = CalculateSum32 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT32) ((UINT32)(-1) - CheckSum + 1); +} + + +/** + Returns the sum of all elements in a buffer of 64-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 64-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT64 +EFIAPI +CalculateSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ) +{ + UINT64 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x7) == 0); + ASSERT ((Length & 0x7) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = Sum + *(Buffer + Count); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 64-bit values. + + This function first calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT64 +EFIAPI +CalculateCheckSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ) +{ + UINT64 CheckSum; + + CheckSum = CalculateSum64 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT64) ((UINT64)(-1) - CheckSum + 1); +} + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mCrcTable[256] = { + 0x00000000, + 0x77073096, + 0xEE0E612C, + 0x990951BA, + 0x076DC419, + 0x706AF48F, + 0xE963A535, + 0x9E6495A3, + 0x0EDB8832, + 0x79DCB8A4, + 0xE0D5E91E, + 0x97D2D988, + 0x09B64C2B, + 0x7EB17CBD, + 0xE7B82D07, + 0x90BF1D91, + 0x1DB71064, + 0x6AB020F2, + 0xF3B97148, + 0x84BE41DE, + 0x1ADAD47D, + 0x6DDDE4EB, + 0xF4D4B551, + 0x83D385C7, + 0x136C9856, + 0x646BA8C0, + 0xFD62F97A, + 0x8A65C9EC, + 0x14015C4F, + 0x63066CD9, + 0xFA0F3D63, + 0x8D080DF5, + 0x3B6E20C8, + 0x4C69105E, + 0xD56041E4, + 0xA2677172, + 0x3C03E4D1, + 0x4B04D447, + 0xD20D85FD, + 0xA50AB56B, + 0x35B5A8FA, + 0x42B2986C, + 0xDBBBC9D6, + 0xACBCF940, + 0x32D86CE3, + 0x45DF5C75, + 0xDCD60DCF, + 0xABD13D59, + 0x26D930AC, + 0x51DE003A, + 0xC8D75180, + 0xBFD06116, + 0x21B4F4B5, + 0x56B3C423, + 0xCFBA9599, + 0xB8BDA50F, + 0x2802B89E, + 0x5F058808, + 0xC60CD9B2, + 0xB10BE924, + 0x2F6F7C87, + 0x58684C11, + 0xC1611DAB, + 0xB6662D3D, + 0x76DC4190, + 0x01DB7106, + 0x98D220BC, + 0xEFD5102A, + 0x71B18589, + 0x06B6B51F, + 0x9FBFE4A5, + 0xE8B8D433, + 0x7807C9A2, + 0x0F00F934, + 0x9609A88E, + 0xE10E9818, + 0x7F6A0DBB, + 0x086D3D2D, + 0x91646C97, + 0xE6635C01, + 0x6B6B51F4, + 0x1C6C6162, + 0x856530D8, + 0xF262004E, + 0x6C0695ED, + 0x1B01A57B, + 0x8208F4C1, + 0xF50FC457, + 0x65B0D9C6, + 0x12B7E950, + 0x8BBEB8EA, + 0xFCB9887C, + 0x62DD1DDF, + 0x15DA2D49, + 0x8CD37CF3, + 0xFBD44C65, + 0x4DB26158, + 0x3AB551CE, + 0xA3BC0074, + 0xD4BB30E2, + 0x4ADFA541, + 0x3DD895D7, + 0xA4D1C46D, + 0xD3D6F4FB, + 0x4369E96A, + 0x346ED9FC, + 0xAD678846, + 0xDA60B8D0, + 0x44042D73, + 0x33031DE5, + 0xAA0A4C5F, + 0xDD0D7CC9, + 0x5005713C, + 0x270241AA, + 0xBE0B1010, + 0xC90C2086, + 0x5768B525, + 0x206F85B3, + 0xB966D409, + 0xCE61E49F, + 0x5EDEF90E, + 0x29D9C998, + 0xB0D09822, + 0xC7D7A8B4, + 0x59B33D17, + 0x2EB40D81, + 0xB7BD5C3B, + 0xC0BA6CAD, + 0xEDB88320, + 0x9ABFB3B6, + 0x03B6E20C, + 0x74B1D29A, + 0xEAD54739, + 0x9DD277AF, + 0x04DB2615, + 0x73DC1683, + 0xE3630B12, + 0x94643B84, + 0x0D6D6A3E, + 0x7A6A5AA8, + 0xE40ECF0B, + 0x9309FF9D, + 0x0A00AE27, + 0x7D079EB1, + 0xF00F9344, + 0x8708A3D2, + 0x1E01F268, + 0x6906C2FE, + 0xF762575D, + 0x806567CB, + 0x196C3671, + 0x6E6B06E7, + 0xFED41B76, + 0x89D32BE0, + 0x10DA7A5A, + 0x67DD4ACC, + 0xF9B9DF6F, + 0x8EBEEFF9, + 0x17B7BE43, + 0x60B08ED5, + 0xD6D6A3E8, + 0xA1D1937E, + 0x38D8C2C4, + 0x4FDFF252, + 0xD1BB67F1, + 0xA6BC5767, + 0x3FB506DD, + 0x48B2364B, + 0xD80D2BDA, + 0xAF0A1B4C, + 0x36034AF6, + 0x41047A60, + 0xDF60EFC3, + 0xA867DF55, + 0x316E8EEF, + 0x4669BE79, + 0xCB61B38C, + 0xBC66831A, + 0x256FD2A0, + 0x5268E236, + 0xCC0C7795, + 0xBB0B4703, + 0x220216B9, + 0x5505262F, + 0xC5BA3BBE, + 0xB2BD0B28, + 0x2BB45A92, + 0x5CB36A04, + 0xC2D7FFA7, + 0xB5D0CF31, + 0x2CD99E8B, + 0x5BDEAE1D, + 0x9B64C2B0, + 0xEC63F226, + 0x756AA39C, + 0x026D930A, + 0x9C0906A9, + 0xEB0E363F, + 0x72076785, + 0x05005713, + 0x95BF4A82, + 0xE2B87A14, + 0x7BB12BAE, + 0x0CB61B38, + 0x92D28E9B, + 0xE5D5BE0D, + 0x7CDCEFB7, + 0x0BDBDF21, + 0x86D3D2D4, + 0xF1D4E242, + 0x68DDB3F8, + 0x1FDA836E, + 0x81BE16CD, + 0xF6B9265B, + 0x6FB077E1, + 0x18B74777, + 0x88085AE6, + 0xFF0F6A70, + 0x66063BCA, + 0x11010B5C, + 0x8F659EFF, + 0xF862AE69, + 0x616BFFD3, + 0x166CCF45, + 0xA00AE278, + 0xD70DD2EE, + 0x4E048354, + 0x3903B3C2, + 0xA7672661, + 0xD06016F7, + 0x4969474D, + 0x3E6E77DB, + 0xAED16A4A, + 0xD9D65ADC, + 0x40DF0B66, + 0x37D83BF0, + 0xA9BCAE53, + 0xDEBB9EC5, + 0x47B2CF7F, + 0x30B5FFE9, + 0xBDBDF21C, + 0xCABAC28A, + 0x53B39330, + 0x24B4A3A6, + 0xBAD03605, + 0xCDD70693, + 0x54DE5729, + 0x23D967BF, + 0xB3667A2E, + 0xC4614AB8, + 0x5D681B02, + 0x2A6F2B94, + 0xB40BBE37, + 0xC30C8EA1, + 0x5A05DF1B, + 0x2D02EF8D +}; + +/** + Computes and returns a 32-bit CRC for a data buffer. + CRC32 value bases on ITU-T V.42. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param[in] Buffer A pointer to the buffer on which the 32-bit CRC is to be computed. + @param[in] Length The number of bytes in the buffer Data. + + @retval Crc32 The 32-bit CRC was computed for the data buffer. + +**/ +UINT32 +EFIAPI +CalculateCrc32( + IN VOID *Buffer, + IN UINTN Length + ) +{ + UINTN Index; + UINT32 Crc; + UINT8 *Ptr; + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + // + // Compute CRC + // + Crc = 0xffffffff; + for (Index = 0, Ptr = Buffer; Index < Length; Index++, Ptr++) { + Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr]; + } + + return Crc ^ 0xffffffff; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c b/roms/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c new file mode 100644 index 000000000..7f07ba2d6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c @@ -0,0 +1,18 @@ +/** @file + Provides hack function for passng GCC build. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Hack function for passing GCC build. +**/ +VOID +__chkstk() +{ +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Cpu.c b/roms/edk2/MdePkg/Library/BaseLib/Cpu.c new file mode 100644 index 000000000..689246f16 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Cpu.c @@ -0,0 +1,59 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ) +{ + BOOLEAN InterruptState; + + InterruptState = GetInterruptState (); + DisableInterrupts (); + return InterruptState; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should be enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ) +{ + if (InterruptState) { + EnableInterrupts (); + } else { + DisableInterrupts (); + } + return InterruptState; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c b/roms/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c new file mode 100644 index 000000000..9e110cacb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c @@ -0,0 +1,32 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include +#include + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ) +{ + volatile UINTN Index; + + for (Index = 0; Index == 0;); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c b/roms/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c new file mode 100644 index 000000000..bdf25b836 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c @@ -0,0 +1,47 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + It is the caller's responsibility to not call this function with a Divisor of 0. + If Divisor is 0, then the quotient and remainder should be assumed to be + the largest negative integer. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemS64x64 (Dividend, Divisor, Remainder); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/DivU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/DivU64x32.c new file mode 100644 index 000000000..fa377ec55 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/DivU64x32.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivU64x32 (Dividend, Divisor); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c b/roms/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c new file mode 100644 index 000000000..df9d3310e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c @@ -0,0 +1,43 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x32 (Dividend, Divisor, Remainder); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c b/roms/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c new file mode 100644 index 000000000..94dc2b1a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c @@ -0,0 +1,43 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x64 (Dividend, Divisor, Remainder); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c b/roms/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c new file mode 100644 index 000000000..d0debec30 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c @@ -0,0 +1,123 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +extern +UINT64 +_break ( + CHAR8 BreakCode + ); + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + _break (3); +} + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ +} + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE means interrupts are currently enabled. Otherwise, + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ) +{ + EnableInterrupts (); + DisableInterrupts (); +} + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c new file mode 100644 index 000000000..631853cd0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c @@ -0,0 +1,62 @@ +/** @file + Implementation of SetJump() and LongJump() on EBC. + + SetJump() and LongJump() are not currently supported for the EBC processor type. + Implementation for EBC just returns 0 for SetJump(), and ASSERT() for LongJump(). + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Saves the current CPU context that can be restored with a call to LongJump() and returns 0. + + Saves the current CPU context in the buffer specified by JumpBuffer and returns 0. The initial + call to SetJump() must always return 0. Subsequent calls to LongJump() cause a non-zero + value to be returned by SetJump(). + + If JumpBuffer is NULL, then ASSERT(). + For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + + @retval 0 Indicates a return from SetJump(). + +**/ +RETURNS_TWICE +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ) +{ + InternalAssertJumpBuffer (JumpBuffer); + return 0; +} + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. + This function never returns to the caller. + Instead it resumes execution based on the state of JumpBuffer. + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is restored. + +**/ +VOID +EFIAPI +InternalLongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ) +{ + // + // This function cannot work on EBC + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c new file mode 100644 index 000000000..d4067a4a0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c @@ -0,0 +1,24 @@ +/** @file + SpeculationBarrier() function for EBC. + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +/** + Uses as a barrier to stop speculative execution. + + Ensures that no later instruction will execute speculatively, until all prior + instructions have completed. + +**/ +VOID +EFIAPI +SpeculationBarrier ( + VOID + ) +{ +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c new file mode 100644 index 000000000..92cbef8d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c @@ -0,0 +1,52 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. + Marker will be ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param Marker A VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +InternalSwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + IN VA_LIST Marker + ) + +{ + // + // This version of this function does not actually change the stack pointer + // This is to support compilation of CPU types that do not support assemblers + // such as EBC + // + EntryPoint (Context1, Context2); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/FilePaths.c b/roms/edk2/MdePkg/Library/BaseLib/FilePaths.c new file mode 100644 index 000000000..c2c561ac6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/FilePaths.c @@ -0,0 +1,115 @@ +/** @file + Defines file-path manipulation functions. + + Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Dell Technologies. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include +#include + +/** + Removes the last directory or file entry in a path. For a path which is + like L"fs0:startup.nsh", it's converted to L"fs0:". + + @param[in,out] Path A pointer to the path to modify. + + @retval FALSE Nothing was found to remove. + @retval TRUE A directory or file was removed. +**/ +BOOLEAN +EFIAPI +PathRemoveLastItem( + IN OUT CHAR16 *Path + ) +{ + CHAR16 *Walker; + CHAR16 *LastSlash; + // + // get directory name from path... ('chop' off extra) + // + for ( Walker = Path, LastSlash = NULL + ; Walker != NULL && *Walker != CHAR_NULL + ; Walker++ + ){ + if (*Walker == L'\\' && *(Walker + 1) != CHAR_NULL) { + LastSlash = Walker+1; + } else if (*Walker == L':' && *(Walker + 1) != L'\\' && *(Walker + 1) != CHAR_NULL) { + LastSlash = Walker+1; + } + } + if (LastSlash != NULL) { + *LastSlash = CHAR_NULL; + return (TRUE); + } + return (FALSE); +} + +/** + Function to clean up paths. + + - Single periods in the path are removed. + - Double periods in the path are removed along with a single parent directory. + - Forward slashes L'/' are converted to backward slashes L'\'. + + This will be done inline and the existing buffer may be larger than required + upon completion. + + @param[in] Path The pointer to the string containing the path. + + @return Returns Path, otherwise returns NULL to indicate that an error has occurred. +**/ +CHAR16* +EFIAPI +PathCleanUpDirectories( + IN CHAR16 *Path +) +{ + CHAR16 *TempString; + + if (Path == NULL) { + return NULL; + } + + // + // Replace the '/' with '\' + // + for (TempString = Path; *TempString != CHAR_NULL; TempString++) { + if (*TempString == L'/') { + *TempString = L'\\'; + } + } + + // + // Replace the "\\" with "\" + // + while ((TempString = StrStr (Path, L"\\\\")) != NULL) { + CopyMem (TempString, TempString + 1, StrSize (TempString + 1)); + } + + // + // Remove all the "\.". E.g.: fs0:\abc\.\def\. + // + while ((TempString = StrStr (Path, L"\\.\\")) != NULL) { + CopyMem (TempString, TempString + 2, StrSize (TempString + 2)); + } + if ((StrLen (Path) >= 2) && (StrCmp (Path + StrLen (Path) - 2, L"\\.") == 0)) { + Path[StrLen (Path) - 1] = CHAR_NULL; + } + + // + // Remove all the "\..". E.g.: fs0:\abc\..\def\.. + // + while (((TempString = StrStr(Path, L"\\..")) != NULL) && + ((*(TempString + 3) == L'\\') || (*(TempString + 3) == CHAR_NULL)) + ) { + *(TempString + 1) = CHAR_NULL; + PathRemoveLastItem(Path); + if (*(TempString + 3) != CHAR_NULL) { + CopyMem (Path + StrLen (Path), TempString + 4, StrSize (TempString + 4)); + } + } + + return Path; +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c b/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c new file mode 100644 index 000000000..76f5e3cfb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c @@ -0,0 +1,38 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ) +{ + if (0 == Operand) { + return 0; + } + + return 1ul << HighBitSet32 (Operand); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c b/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c new file mode 100644 index 000000000..5033076f8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c @@ -0,0 +1,38 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ) +{ + if (Operand == 0) { + return 0; + } + + return LShiftU64 (1, (UINTN) HighBitSet64 (Operand)); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/HighBitSet32.c b/roms/edk2/MdePkg/Library/BaseLib/HighBitSet32.c new file mode 100644 index 000000000..b3c9ed158 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/HighBitSet32.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return - 1; + } + for (BitIndex = 31; (INT32)Operand > 0; BitIndex--, Operand <<= 1); + return BitIndex; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/HighBitSet64.c b/roms/edk2/MdePkg/Library/BaseLib/HighBitSet64.c new file mode 100644 index 000000000..4f06dfc88 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/HighBitSet64.c @@ -0,0 +1,49 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ) +{ + if (Operand == (UINT32)Operand) { + // + // Operand is just a 32-bit integer + // + return HighBitSet32 ((UINT32)Operand); + } + + // + // Operand is really a 64-bit integer + // + if (sizeof (UINTN) == sizeof (UINT32)) { + return HighBitSet32 (((UINT32*)&Operand)[1]) + 32; + } else { + return HighBitSet32 ((UINT32)RShiftU64 (Operand, 32)) + 32; + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c new file mode 100644 index 000000000..836108364 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c @@ -0,0 +1,45 @@ +/** @file + 64-bit arithmetic right shift function for IA-32. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits + are filled with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand arithmetically shifted right by Count. + +**/ +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + _asm { + mov cl, byte ptr [Count] + mov eax, dword ptr [Operand + 4] + cdq + test cl, 32 + jnz L0 + mov edx, eax + mov eax, dword ptr [Operand + 0] +L0: + shrd eax, edx, cl + sar edx, cl + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm new file mode 100644 index 000000000..94aa88229 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ARShiftU64.nasm +; +; Abstract: +; +; 64-bit arithmetic right shift function for IA-32 +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathARShiftU64 ( +; IN UINT64 Operand, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathARShiftU64) +ASM_PFX(InternalMathARShiftU64): + mov cl, [esp + 12] + mov eax, [esp + 8] + cdq + test cl, 32 + jnz .0 + mov edx, eax + mov eax, [esp + 4] +.0: + shrd eax, edx, cl + sar edx, cl + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c new file mode 100644 index 000000000..a59da0cee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c @@ -0,0 +1,35 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +void __debugbreak (VOID); + +#pragma intrinsic(__debugbreak) + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __debugbreak (); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm new file mode 100644 index 000000000..a62e4f5c3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm @@ -0,0 +1,30 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuBreakpoint.Asm +; +; Abstract: +; +; CpuBreakpoint function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuBreakpoint ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuBreakpoint) +ASM_PFX(CpuBreakpoint): + int 3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c new file mode 100644 index 000000000..bcb0fa78f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c @@ -0,0 +1,68 @@ +/** @file + AsmCpuid function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and x64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param RegisterEax A pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param RegisterEbx A pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param RegisterEcx A pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param RegisterEdx A pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *RegisterEax, OPTIONAL + OUT UINT32 *RegisterEbx, OPTIONAL + OUT UINT32 *RegisterEcx, OPTIONAL + OUT UINT32 *RegisterEdx OPTIONAL + ) +{ + _asm { + mov eax, Index + cpuid + push ecx + mov ecx, RegisterEax + jecxz SkipEax + mov [ecx], eax +SkipEax: + mov ecx, RegisterEbx + jecxz SkipEbx + mov [ecx], ebx +SkipEbx: + pop eax + mov ecx, RegisterEcx + jecxz SkipEcx + mov [ecx], eax +SkipEcx: + mov ecx, RegisterEdx + jecxz SkipEdx + mov [ecx], edx +SkipEdx: + mov eax, Index + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm new file mode 100644 index 000000000..d38135fcd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmCpuid ( +; IN UINT32 RegisterInEax, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmCpuid) +ASM_PFX(AsmCpuid): + push ebx + push ebp + mov ebp, esp + mov eax, [ebp + 12] + cpuid + push ecx + mov ecx, [ebp + 16] + jecxz .0 + mov [ecx], eax +.0: + mov ecx, [ebp + 20] + jecxz .1 + mov [ecx], ebx +.1: + mov ecx, [ebp + 24] + jecxz .2 + pop DWORD [ecx] +.2: + mov ecx, [ebp + 28] + jecxz .3 + mov [ecx], edx +.3: + mov eax, [ebp + 12] + leave + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c new file mode 100644 index 000000000..b537182a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c @@ -0,0 +1,76 @@ +/** @file + AsmCpuidEx function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Retrieves CPUID information using an extended leaf identifier. + + Executes the CPUID instruction with EAX set to the value specified by Index + and ECX set to the value specified by SubIndex. This function always returns + Index. This function is only available on IA-32 and x64. + + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + + @param Index The 32-bit value to load into EAX prior to invoking the + CPUID instruction. + @param SubIndex The 32-bit value to load into ECX prior to invoking the + CPUID instruction. + @param RegisterEax A pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param RegisterEbx A pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param RegisterEcx A pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param RegisterEdx A pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *RegisterEax, OPTIONAL + OUT UINT32 *RegisterEbx, OPTIONAL + OUT UINT32 *RegisterEcx, OPTIONAL + OUT UINT32 *RegisterEdx OPTIONAL + ) +{ + _asm { + mov eax, Index + mov ecx, SubIndex + cpuid + push ecx + mov ecx, RegisterEax + jecxz SkipEax + mov [ecx], eax +SkipEax: + mov ecx, RegisterEbx + jecxz SkipEbx + mov [ecx], ebx +SkipEbx: + pop eax + mov ecx, RegisterEcx + jecxz SkipEcx + mov [ecx], eax +SkipEcx: + mov ecx, RegisterEdx + jecxz SkipEdx + mov [ecx], edx +SkipEdx: + mov eax, Index + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm new file mode 100644 index 000000000..f381069c6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm @@ -0,0 +1,61 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuIdEx.Asm +; +; Abstract: +; +; AsmCpuidEx function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmCpuidEx ( +; IN UINT32 RegisterInEax, +; IN UINT32 RegisterInEcx, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(AsmCpuidEx) +ASM_PFX(AsmCpuidEx): + push ebx + push ebp + mov ebp, esp + mov eax, [ebp + 12] + mov ecx, [ebp + 16] + cpuid + push ecx + mov ecx, [ebp + 20] + jecxz .0 + mov [ecx], eax +.0: + mov ecx, [ebp + 24] + jecxz .1 + mov [ecx], ebx +.1: + mov ecx, [ebp + 32] + jecxz .2 + mov [ecx], edx +.2: + mov ecx, [ebp + 28] + jecxz .3 + pop DWORD [ecx] +.3: + mov eax, [ebp + 12] + leave + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c new file mode 100644 index 000000000..12dc896fe --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c @@ -0,0 +1,29 @@ +/** @file + CpuPause function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + _asm { + pause + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm new file mode 100644 index 000000000..8fac8c518 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm @@ -0,0 +1,30 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuPause.Asm +; +; Abstract: +; +; CpuPause function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuPause ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuPause) +ASM_PFX(CpuPause): + pause + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c new file mode 100644 index 000000000..6a8be4ef2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c @@ -0,0 +1,30 @@ +/** @file + AsmDisableCache function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmDisableCache ( + VOID + ) +{ + _asm { + mov eax, cr0 + bts eax, 30 + btr eax, 29 + mov cr0, eax + wbinvd + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm new file mode 100644 index 000000000..c379e4a6b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisableCache.Asm +; +; Abstract: +; +; Set the CD bit of CR0 to 1, clear the NW bit of CR0 to 0, and flush all caches with a +; WBINVD instruction. +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmDisableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmDisableCache) +ASM_PFX(AsmDisableCache): + mov eax, cr0 + bts eax, 30 + btr eax, 29 + mov cr0, eax + wbinvd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c new file mode 100644 index 000000000..4141ef751 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c @@ -0,0 +1,26 @@ +/** @file + DisableInterrupts function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + _asm { + cli + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm new file mode 100644 index 000000000..ed73f66be --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisableInterrupts.Asm +; +; Abstract: +; +; DisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; DisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(DisableInterrupts) +ASM_PFX(DisableInterrupts): + cli + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c new file mode 100644 index 000000000..12ee87413 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c @@ -0,0 +1,71 @@ +/** @file + AsmDisablePaging32 function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +__declspec (naked) +VOID +EFIAPI +InternalX86DisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + _asm { + push ebp + mov ebp, esp + mov ebx, EntryPoint + mov ecx, Context1 + mov edx, Context2 + pushfd + pop edi // save EFLAGS to edi + cli + mov eax, cr0 + btr eax, 31 + mov esp, NewStack + mov cr0, eax + push edi + popfd // restore EFLAGS from edi + push edx + push ecx + call ebx + jmp $ // EntryPoint() should not return + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm new file mode 100644 index 000000000..0cab3304a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisablePaging32.Asm +; +; Abstract: +; +; AsmDisablePaging32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86DisablePaging32 ( +; IN SWITCH_STACK_ENTRY_POINT EntryPoint, +; IN VOID *Context1, OPTIONAL +; IN VOID *Context2, OPTIONAL +; IN VOID *NewStack +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86DisablePaging32) +ASM_PFX(InternalX86DisablePaging32): + mov ebx, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + pushfd + pop edi ; save EFLAGS to edi + cli + mov eax, cr0 + btr eax, 31 + mov esp, [esp + 16] + mov cr0, eax + push edi + popfd ; restore EFLAGS from edi + push edx + push ecx + call ebx + jmp $ ; EntryPoint() should not return + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c new file mode 100644 index 000000000..4e6496404 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c @@ -0,0 +1,47 @@ +/** @file + Integer division worker functions for Ia32. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Worker function that Divides a 64-bit signed integer by a 64-bit signed integer and + generates a 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit + signed value Divisor and generates a 64-bit signed quotient. If Remainder + is not NULL, then the 64-bit signed remainder is returned in Remainder. + This function returns the 64-bit signed quotient. + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ) +{ + INT64 Quot; + + Quot = InternalMathDivRemU64x64 ( + (UINT64) (Dividend >= 0 ? Dividend : -Dividend), + (UINT64) (Divisor >= 0 ? Divisor : -Divisor), + (UINT64 *) Remainder + ); + if (Remainder != NULL && Dividend < 0) { + *Remainder = -*Remainder; + } + return (Dividend ^ Divisor) >= 0 ? Quot : -Quot; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c new file mode 100644 index 000000000..538f77a83 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c @@ -0,0 +1,44 @@ +/** @file + Calculate the quotient of a 64-bit integer by a 32-bit integer + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + _asm { + mov eax, dword ptr [Dividend + 4] + mov ecx, Divisor + xor edx, edx + div ecx + push eax ; save quotient on stack + mov eax, dword ptr [Dividend] + div ecx + pop edx ; restore high-order dword of the quotient + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm new file mode 100644 index 000000000..d462119d4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DivU64x32.nasm +; +; Abstract: +; +; Calculate the quotient of a 64-bit integer by a 32-bit integer +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathDivU64x32 ( +; IN UINT64 Dividend, +; IN UINT32 Divisor +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathDivU64x32) +ASM_PFX(InternalMathDivU64x32): + mov eax, [esp + 8] + mov ecx, [esp + 12] + xor edx, edx + div ecx + push eax ; save quotient on stack + mov eax, [esp + 8] + div ecx + pop edx ; restore high-order dword of the quotient + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c new file mode 100644 index 000000000..035d4340d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c @@ -0,0 +1,49 @@ +/** @file + Set error flag for all division functions + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder + ) +{ + _asm { + mov ecx, Divisor + mov eax, dword ptr [Dividend + 4] + xor edx, edx + div ecx + push eax + mov eax, dword ptr [Dividend + 0] + div ecx + mov ecx, Remainder + jecxz RemainderNull // abandon remainder if Remainder == NULL + mov [ecx], edx +RemainderNull: + pop edx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm new file mode 100644 index 000000000..944ba73f1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DivError.asm +; +; Abstract: +; +; Set error flag for all division functions +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathDivRemU64x32 ( +; IN UINT64 Dividend, +; IN UINT32 Divisor, +; OUT UINT32 *Remainder +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathDivRemU64x32) +ASM_PFX(InternalMathDivRemU64x32): + mov ecx, [esp + 12] ; ecx <- divisor + mov eax, [esp + 8] ; eax <- dividend[32..63] + xor edx, edx + div ecx ; eax <- quotient[32..63], edx <- remainder + push eax + mov eax, [esp + 8] ; eax <- dividend[0..31] + div ecx ; eax <- quotient[0..31] + mov ecx, [esp + 20] ; ecx <- Remainder + jecxz .0 ; abandon remainder if Remainder == NULL + mov [ecx], edx +.0: + pop edx ; edx <- quotient[32..63] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm new file mode 100644 index 000000000..0adb07f73 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm @@ -0,0 +1,88 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DivU64x64Remainder.nasm +; +; Abstract: +; +; Calculate the quotient of a 64-bit integer by a 64-bit integer and returns +; both the quotient and the remainder +; +;------------------------------------------------------------------------------ + + SECTION .text + +extern ASM_PFX(InternalMathDivRemU64x32) + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathDivRemU64x64 ( +; IN UINT64 Dividend, +; IN UINT64 Divisor, +; OUT UINT64 *Remainder OPTIONAL +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathDivRemU64x64) +ASM_PFX(InternalMathDivRemU64x64): + mov ecx, [esp + 16] ; ecx <- divisor[32..63] + test ecx, ecx + jnz _@DivRemU64x64 ; call _@DivRemU64x64 if Divisor > 2^32 + mov ecx, [esp + 20] + jecxz .0 + and dword [ecx + 4], 0 ; zero high dword of remainder + mov [esp + 16], ecx ; set up stack frame to match DivRemU64x32 +.0: + jmp ASM_PFX(InternalMathDivRemU64x32) + +_@DivRemU64x64: + push ebx + push esi + push edi + mov edx, dword [esp + 20] + mov eax, dword [esp + 16] ; edx:eax <- dividend + mov edi, edx + mov esi, eax ; edi:esi <- dividend + mov ebx, dword [esp + 24] ; ecx:ebx <- divisor +.1: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz .1 + div ebx + mov ebx, eax ; ebx <- quotient + mov ecx, [esp + 28] ; ecx <- high dword of divisor + mul dword [esp + 24] ; edx:eax <- quotient * divisor[0..31] + imul ecx, ebx ; ecx <- quotient * divisor[32..63] + add edx, ecx ; edx <- (quotient * divisor)[32..63] + mov ecx, dword [esp + 32] ; ecx <- addr for Remainder + jc @TooLarge ; product > 2^64 + cmp edi, edx ; compare high 32 bits + ja @Correct + jb @TooLarge ; product > dividend + cmp esi, eax + jae @Correct ; product <= dividend +@TooLarge: + dec ebx ; adjust quotient by -1 + jecxz @Return ; return if Remainder == NULL + sub eax, dword [esp + 24] + sbb edx, dword [esp + 28] ; edx:eax <- (quotient - 1) * divisor +@Correct: + jecxz @Return + sub esi, eax + sbb edi, edx ; edi:esi <- remainder + mov [ecx], esi + mov [ecx + 4], edi +@Return: + mov eax, ebx ; eax <- quotient + xor edx, edx ; quotient is 32 bits long + pop edi + pop esi + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c new file mode 100644 index 000000000..4f5c6e9ab --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c @@ -0,0 +1,30 @@ +/** @file + AsmEnableCache function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmEnableCache ( + VOID + ) +{ + _asm { + wbinvd + mov eax, cr0 + btr eax, 30 + btr eax, 29 + mov cr0, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm new file mode 100644 index 000000000..02ed72921 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableCache.Asm +; +; Abstract: +; +; Flush all caches with a WBINVD instruction, clear the CD bit of CR0 to 0, and clear +; the NW bit of CR0 to 0 +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmEnableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmEnableCache) +ASM_PFX(AsmEnableCache): + wbinvd + mov eax, cr0 + btr eax, 29 + btr eax, 30 + mov cr0, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c new file mode 100644 index 000000000..7ec62147f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c @@ -0,0 +1,30 @@ +/** @file + EnableDisableInterrupts function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ) +{ + _asm { + sti + nop + nop + cli + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm new file mode 100644 index 000000000..2da094f0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableDisableInterrupts.Asm +; +; Abstract: +; +; EnableDisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableDisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(EnableDisableInterrupts) +ASM_PFX(EnableDisableInterrupts): + sti + cli + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c new file mode 100644 index 000000000..bc03144c4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c @@ -0,0 +1,26 @@ +/** @file + EnableInterrupts function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + _asm { + sti + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm new file mode 100644 index 000000000..979e70820 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableInterrupts.Asm +; +; Abstract: +; +; EnableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(EnableInterrupts) +ASM_PFX(EnableInterrupts): + sti + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c new file mode 100644 index 000000000..ce0c71067 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c @@ -0,0 +1,75 @@ +/** @file + AsmEnablePaging32 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +__declspec (naked) +VOID +EFIAPI +InternalX86EnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + _asm { + push ebp + mov ebp, esp + mov ebx, EntryPoint + mov ecx, Context1 + mov edx, Context2 + pushfd + pop edi + cli + mov eax, cr0 + bts eax, 31 + mov esp, NewStack + mov cr0, eax + push edi + popfd + push edx + push ecx + call ebx + jmp $ + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm new file mode 100644 index 000000000..3f00167b3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnablePaging32.Asm +; +; Abstract: +; +; AsmEnablePaging32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86EnablePaging32 ( +; IN SWITCH_STACK_ENTRY_POINT EntryPoint, +; IN VOID *Context1, OPTIONAL +; IN VOID *Context2, OPTIONAL +; IN VOID *NewStack +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86EnablePaging32) +ASM_PFX(InternalX86EnablePaging32): + mov ebx, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + pushfd + pop edi ; save flags in edi + cli + mov eax, cr0 + bts eax, 31 + mov esp, [esp + 16] + mov cr0, eax + push edi + popfd ; restore flags + push edx + push ecx + call ebx + jmp $ + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm new file mode 100644 index 000000000..544e3c389 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnablePaging64.Asm +; +; Abstract: +; +; AsmEnablePaging64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86EnablePaging64 ( +; IN UINT16 Cs, +; IN UINT64 EntryPoint, +; IN UINT64 Context1, OPTIONAL +; IN UINT64 Context2, OPTIONAL +; IN UINT64 NewStack +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86EnablePaging64) +ASM_PFX(InternalX86EnablePaging64): + cli + mov DWORD [esp], .0 ; offset for far retf, seg is the 1st arg + mov eax, cr4 + or al, (1 << 5) + mov cr4, eax ; enable PAE + mov ecx, 0xc0000080 + rdmsr + or ah, 1 ; set LME + wrmsr + mov eax, cr0 + bts eax, 31 ; set PG + mov cr0, eax ; enable paging + retf ; topmost 2 dwords hold the address +.0: + DB 0x67, 0x48 ; 32-bit address size, 64-bit operand size + mov ebx, [esp] ; mov rbx, [esp] + DB 0x67, 0x48 + mov ecx, [esp + 8] ; mov rcx, [esp + 8] + DB 0x67, 0x48 + mov edx, [esp + 0x10] ; mov rdx, [esp + 10h] + DB 0x67, 0x48 + mov esp, [esp + 0x18] ; mov rsp, [esp + 18h] + DB 0x48 + add esp, -0x20 ; add rsp, -20h + call ebx ; call rbx + hlt ; no one should get here + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c new file mode 100644 index 000000000..8fbda0670 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c @@ -0,0 +1,52 @@ +/** @file + AsmFlushCacheLine function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and x64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + // + // If the CPU does not support CLFLUSH instruction, + // then promote flush range to flush entire cache. + // + _asm { + mov eax, 1 + cpuid + test edx, BIT19 + jz NoClflush + mov eax, dword ptr [LinearAddress] + clflush [eax] + jmp Done +NoClflush: + wbinvd +Done: + } + + return LinearAddress; +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm new file mode 100644 index 000000000..8afd4cbdc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FlushCacheLine.Asm +; +; Abstract: +; +; AsmFlushCacheLine function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; AsmFlushCacheLine ( +; IN VOID *LinearAddress +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmFlushCacheLine) +ASM_PFX(AsmFlushCacheLine): + ; + ; If the CPU does not support CLFLUSH instruction, + ; then promote flush range to flush entire cache. + ; + mov eax, 1 + push ebx + cpuid + pop ebx + mov eax, [esp + 4] + test edx, BIT19 + jz .0 + clflush [eax] + ret +.0: + wbinvd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c new file mode 100644 index 000000000..ddd1e4903 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c @@ -0,0 +1,34 @@ +/** @file + AsmFxRestore function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and x64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + _asm { + mov eax, Buffer + fxrstor [eax] + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm new file mode 100644 index 000000000..c48746890 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FxRestore.Asm +; +; Abstract: +; +; AsmFxRestore function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxRestore ( +; IN CONST IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86FxRestore) +ASM_PFX(InternalX86FxRestore): + mov eax, [esp + 4] ; Buffer must be 16-byte aligned + fxrstor [eax] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c new file mode 100644 index 000000000..a8c888217 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c @@ -0,0 +1,34 @@ +/** @file + AsmFxSave function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and x64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + _asm { + mov eax, Buffer + fxsave [eax] + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm new file mode 100644 index 000000000..c1982c064 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FxSave.Asm +; +; Abstract: +; +; AsmFxSave function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxSave ( +; OUT IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86FxSave) +ASM_PFX(InternalX86FxSave): + mov eax, [esp + 4] ; Buffer must be 16-byte aligned + fxsave [eax] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c new file mode 100644 index 000000000..6ed938187 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c @@ -0,0 +1,586 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions. + + Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + // This is a little bit of overkill and it is more about the compiler that it is + // actually processor synchronization. This is like the _ReadWriteBarrier + // Microsoft specific intrinsic + __asm__ __volatile__ ("":::"memory"); +} + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + __asm__ __volatile__ ("pause"); +} + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __asm__ __volatile__ ("int $3"); +} + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ) +{ + UINTN Eflags; + + __asm__ __volatile__ ( + "pushfl \n\t" + "popl %0 " + : "=r" (Eflags) + ); + + return Eflags; +} + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxsave %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxrstor %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and X64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm0, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and X64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm1, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and X64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm2, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and X64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm3, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and X64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm4, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and X64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm5, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and X64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm6, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and X64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm7, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm0" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm1" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm2" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm3" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm4" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm5" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm6" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm7" // %0 + : + : "m" (Value) + ); +} + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and X64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "rdtsc" + : "=A" (Data) + ); + + return Data; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c new file mode 100644 index 000000000..30aa63243 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c @@ -0,0 +1,1170 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions that use + privlidged instructions. + + Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "rdmsr" + : "=A" (Data) // %0 + : "c" (Index) // %1 + ); + + return Data; +} + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "wrmsr" + : + : "c" (Index), + "A" (Value) + ); + + return Value; +} + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr0,%0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr2, %0" + : "=r" (Data) + ); + + return Data; +} + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr3, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr4, %0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr0" + : + : "r" (Cr0) + ); + return Cr0; +} + + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr2" + : + : "r" (Cr2) + ); + return Cr2; +} + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr3" + : + : "r" (Cr3) + ); + return Cr3; +} + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr4" + : + : "r" (Cr4) + ); + return Cr4; +} + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr0, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr1, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr2, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr3, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr4, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr5, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr6, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr7, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr0" + : + : "r" (Dr0) + ); + return Dr0; +} + + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr1" + : + : "r" (Dr1) + ); + return Dr1; +} + + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr2" + : + : "r" (Dr2) + ); + return Dr2; +} + + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr3" + : + : "r" (Dr3) + ); + return Dr3; +} + + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr4" + : + : "r" (Dr4) + ); + return Dr4; +} + + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr5" + : + : "r" (Dr5) + ); + return Dr5; +} + + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr6" + : + : "r" (Dr6) + ); + return Dr6; +} + + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr7" + : + : "r" (Dr7) + ); + return Dr7; +} + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and X64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%cs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and X64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and X64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%es, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and X64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%fs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and X64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%gs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and X64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and X64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "str %0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "sgdt %0" + : "=m" (*Gdtr) + ); +} + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "lgdt %0" + : + : "m" (*Gdtr) + ); + +} + + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "sidt %0" + : "=m" (*Idtr) + ); +} + + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "lidt %0" + : + : "m" (*Idtr) + ); +} + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and X64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "sldt %0" + : "=g" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current Local Descriptor Table Register (GDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and X64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + __asm__ __volatile__ ( + "lldtw %0" + : + : "g" (Ldtr) // %0 + ); +} + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and X64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "rdpmc" + : "=A" (Data) + : "c" (Index) + ); + + return Data; +} + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ) +{ + __asm__ __volatile__ ("wbinvd":::"memory"); +} + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ) +{ + __asm__ __volatile__ ("invd":::"memory"); + +} + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and X64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + UINT32 RegEdx; + + // + // If the CPU does not support CLFLUSH instruction, + // then promote flush range to flush entire cache. + // + AsmCpuid (0x01, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT19) == 0) { + __asm__ __volatile__ ("wbinvd":::"memory"); + return LinearAddress; + } + + + __asm__ __volatile__ ( + "clflush (%0)" + : "+a" (LinearAddress) + : + : "memory" + ); + + return LinearAddress; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c new file mode 100644 index 000000000..6f4cf79e6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c @@ -0,0 +1,54 @@ +/** @file + SwitchStack() function for IA-32. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. + Marker will be ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param Marker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +InternalSwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + IN VA_LIST Marker + ) +{ + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + JumpBuffer.Eip = (UINTN)EntryPoint; + JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*); + JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2); + ((VOID**)JumpBuffer.Esp)[1] = Context1; + ((VOID**)JumpBuffer.Esp)[2] = Context2; + + LongJump (&JumpBuffer, (UINTN)-1); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm new file mode 100644 index 000000000..adfcdf779 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2011, Apple Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InternalSwitchStack.nasm +; +; Abstract: +; +; Implementation of a stack switch on IA-32. +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalSwitchStack ( +; IN SWITCH_STACK_ENTRY_POINT EntryPoint, +; IN VOID *Context1, OPTIONAL +; IN VOID *Context2, OPTIONAL +; IN VOID *NewStack +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSwitchStack) +ASM_PFX(InternalSwitchStack): + push ebp + mov ebp, esp + + mov esp, [ebp + 20] ; switch stack + sub esp, 8 + mov eax, [ebp + 16] + mov [esp + 4], eax + mov eax, [ebp + 12] + mov [esp], eax + push 0 ; keeps gdb from unwinding stack + jmp dword [ebp + 8] ; call and never return diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c new file mode 100644 index 000000000..9870cf9c6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c @@ -0,0 +1,29 @@ +/** @file + AsmInvd function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ) +{ + _asm { + invd + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm new file mode 100644 index 000000000..f6d1beb1b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Invd.Asm +; +; Abstract: +; +; AsmInvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmInvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmInvd) +ASM_PFX(AsmInvd): + invd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c new file mode 100644 index 000000000..87d370c6f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c @@ -0,0 +1,49 @@ +/** @file + 64-bit left rotation for Ia32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling + the low bits with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + _asm { + mov cl, byte ptr [Count] + mov edx, dword ptr [Operand + 4] + mov eax, dword ptr [Operand + 0] + shld ebx, edx, cl + shld edx, eax, cl + ror ebx, cl + shld eax, ebx, cl + test cl, 32 ; Count >= 32? + jz L0 + mov ecx, eax + mov eax, edx + mov edx, ecx +L0: + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm new file mode 100644 index 000000000..3922ae229 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; LRotU64.nasm +; +; Abstract: +; +; 64-bit left rotation for Ia32 +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathLRotU64 ( +; IN UINT64 Operand, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathLRotU64) +ASM_PFX(InternalMathLRotU64): + push ebx + mov cl, [esp + 16] + mov edx, [esp + 12] + mov eax, [esp + 8] + shld ebx, edx, cl + shld edx, eax, cl + ror ebx, cl + shld eax, ebx, cl + test cl, 32 ; Count >= 32? + jz .0 + mov ecx, eax + mov eax, edx + mov edx, ecx +.0: + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c new file mode 100644 index 000000000..1604e7e2f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c @@ -0,0 +1,45 @@ +/** @file + 64-bit left shift function for IA-32. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + _asm { + mov cl, byte ptr [Count] + xor eax, eax + mov edx, dword ptr [Operand + 0] + test cl, 32 // Count >= 32? + jnz L0 + mov eax, edx + mov edx, dword ptr [Operand + 4] +L0: + shld edx, eax, cl + shl eax, cl + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm new file mode 100644 index 000000000..26c38a122 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; LShiftU64.nasm +; +; Abstract: +; +; 64-bit left shift function for IA-32 +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathLShiftU64 ( +; IN UINT64 Operand, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathLShiftU64) +ASM_PFX(InternalMathLShiftU64): + mov cl, [esp + 12] + xor eax, eax + mov edx, [esp + 4] + test cl, 32 ; Count >= 32? + jnz .0 + mov eax, edx + mov edx, [esp + 8] +.0: + shld edx, eax, cl + shl eax, cl + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm new file mode 100644 index 000000000..44478be35 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm @@ -0,0 +1,30 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2018, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Lfence.nasm +; +; Abstract: +; +; Performs a serializing operation on all load-from-memory instructions that +; were issued prior to the call of this function. +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmLfence ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmLfence) +ASM_PFX(AsmLfence): + lfence + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm new file mode 100644 index 000000000..f94d10f80 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm @@ -0,0 +1,60 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; LongJump.Asm +; +; Abstract: +; +; Implementation of _LongJump() on IA-32. +; +;------------------------------------------------------------------------------ + +%include "Nasm.inc" + + SECTION .text + +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalLongJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalLongJump) +ASM_PFX(InternalLongJump): + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov edx, [esp + 4] ; edx = JumpBuffer + mov edx, [edx + 24] ; edx = target SSP + READSSP_EAX + sub edx, eax ; edx = delta + mov eax, edx ; eax = delta + + shr eax, 2 ; eax = delta/sizeof(UINT32) + INCSSP_EAX + +CetDone: + + pop eax ; skip return address + pop edx ; edx <- JumpBuffer + pop eax ; eax <- Value + mov ebx, [edx] + mov esi, [edx + 4] + mov edi, [edx + 8] + mov ebp, [edx + 12] + mov esp, [edx + 16] + jmp dword [edx + 20] ; restore "eip" + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c new file mode 100644 index 000000000..26a19cbd9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c @@ -0,0 +1,42 @@ +/** @file + Calculate the remainder of a 64-bit integer by a 32-bit integer + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor + +**/ +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + _asm { + mov eax, dword ptr [Dividend + 4] + mov ecx, Divisor + xor edx, edx + div ecx + mov eax, dword ptr [Dividend + 0] + div ecx + mov eax, edx + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm new file mode 100644 index 000000000..9f05fded3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DivU64x32.asm +; +; Abstract: +; +; Calculate the remainder of a 64-bit integer by a 32-bit integer +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalMathModU64x32 ( +; IN UINT64 Dividend, +; IN UINT32 Divisor +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathModU64x32) +ASM_PFX(InternalMathModU64x32): + mov eax, [esp + 8] + mov ecx, [esp + 12] + xor edx, edx + div ecx + mov eax, [esp + 4] + div ecx + mov eax, edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c new file mode 100644 index 000000000..966b128a3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c @@ -0,0 +1,42 @@ +/** @file + AsmMonitor function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and x64. + + @param RegisterEax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param RegisterEcx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param RegisterEdx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return RegisterEax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN RegisterEax, + IN UINTN RegisterEcx, + IN UINTN RegisterEdx + ) +{ + _asm { + mov eax, RegisterEax + mov ecx, RegisterEcx + mov edx, RegisterEdx + _emit 0x0f // monitor + _emit 0x01 + _emit 0xc8 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm new file mode 100644 index 000000000..28dc0ba70 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Monitor.Asm +; +; Abstract: +; +; AsmMonitor function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmMonitor ( +; IN UINTN Eax, +; IN UINTN Ecx, +; IN UINTN Edx +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmMonitor) +ASM_PFX(AsmMonitor): + mov eax, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + DB 0xf, 1, 0xc8 ; monitor + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c new file mode 100644 index 000000000..a72868464 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c @@ -0,0 +1,41 @@ +/** @file + Calculate the product of a 64-bit integer and a 32-bit integer + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Multiples a 64-bit unsigned integer by a 32-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + _asm { + mov ecx, Multiplier + mov eax, ecx + imul ecx, dword ptr [Multiplicand + 4] // overflow not detectable + mul dword ptr [Multiplicand + 0] + add edx, ecx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm new file mode 100644 index 000000000..f7591b120 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; MultU64x32.nasm +; +; Abstract: +; +; Calculate the product of a 64-bit integer and a 32-bit integer +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathMultU64x32 ( +; IN UINT64 Multiplicand, +; IN UINT32 Multiplier +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathMultU64x32) +ASM_PFX(InternalMathMultU64x32): + mov ecx, [esp + 12] + mov eax, ecx + imul ecx, [esp + 8] ; overflow not detectable + mul dword [esp + 4] + add edx, ecx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c new file mode 100644 index 000000000..806cbd565 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c @@ -0,0 +1,45 @@ +/** @file + Calculate the product of a 64-bit integer and another 64-bit integer + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + _asm { + mov ebx, dword ptr [Multiplicand + 0] + mov edx, dword ptr [Multiplier + 0] + mov ecx, ebx + mov eax, edx + imul ebx, dword ptr [Multiplier + 4] + imul edx, dword ptr [Multiplicand + 4] + add ebx, edx + mul ecx + add edx, ebx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm new file mode 100644 index 000000000..c128022f9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; MultU64x64.nasm +; +; Abstract: +; +; Calculate the product of a 64-bit integer and another 64-bit integer +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathMultU64x64 ( +; IN UINT64 Multiplicand, +; IN UINT64 Multiplier +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathMultU64x64) +ASM_PFX(InternalMathMultU64x64): + push ebx + mov ebx, [esp + 8] ; ebx <- M1[0..31] + mov edx, [esp + 16] ; edx <- M2[0..31] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 20] ; ebx <- M1[0..31] * M2[32..63] + imul edx, [esp + 12] ; edx <- M1[32..63] * M2[0..31] + add ebx, edx ; carries are abandoned + mul ecx ; edx:eax <- M1[0..31] * M2[0..31] + add edx, ebx ; carries are abandoned + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c new file mode 100644 index 000000000..08c666f79 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c @@ -0,0 +1,38 @@ +/** @file + AsmMwait function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and x64. + + @param RegisterEax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param RegisterEcx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return RegisterEax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN RegisterEax, + IN UINTN RegisterEcx + ) +{ + _asm { + mov eax, RegisterEax + mov ecx, RegisterEcx + _emit 0x0f // mwait + _emit 0x01 + _emit 0xC9 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm new file mode 100644 index 000000000..3956940ca --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Mwait.Asm +; +; Abstract: +; +; AsmMwait function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmMwait ( +; IN UINTN Eax, +; IN UINTN Ecx +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmMwait) +ASM_PFX(AsmMwait): + mov eax, [esp + 4] + mov ecx, [esp + 8] + DB 0xf, 1, 0xc9 ; mwait + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c new file mode 100644 index 000000000..889ece463 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c @@ -0,0 +1,51 @@ +/** @file + Non-existing BaseLib functions on Ia32 + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + @param CodeSelector The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +InternalX86DisablePaging64 ( + IN UINT16 CodeSelector, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + // + // This function cannot work on IA32 platform + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c new file mode 100644 index 000000000..82711a5f8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c @@ -0,0 +1,49 @@ +/** @file + 64-bit right rotation for Ia32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling + the high bits with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + _asm { + mov cl, byte ptr [Count] + mov eax, dword ptr [Operand + 0] + mov edx, dword ptr [Operand + 4] + shrd ebx, eax, cl + shrd eax, edx, cl + rol ebx, cl + shrd edx, ebx, cl + test cl, 32 // Count >= 32? + jz L0 + mov ecx, eax + mov eax, edx + mov edx, ecx +L0: + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm new file mode 100644 index 000000000..7e4646e1e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RRotU64.nasm +; +; Abstract: +; +; 64-bit right rotation for Ia32 +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathRRotU64 ( +; IN UINT64 Operand, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathRRotU64) +ASM_PFX(InternalMathRRotU64): + push ebx + mov cl, [esp + 16] + mov eax, [esp + 8] + mov edx, [esp + 12] + shrd ebx, eax, cl + shrd eax, edx, cl + rol ebx, cl + shrd edx, ebx, cl + test cl, 32 ; Count >= 32? + jz .0 + mov ecx, eax ; switch eax & edx if Count >= 32 + mov eax, edx + mov edx, ecx +.0: + pop ebx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c new file mode 100644 index 000000000..35d843705 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c @@ -0,0 +1,45 @@ +/** @file + 64-bit logical right shift function for IA-32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + _asm { + mov cl, byte ptr [Count] + xor edx, edx + mov eax, dword ptr [Operand + 4] + test cl, 32 + jnz L0 + mov edx, eax + mov eax, dword ptr [Operand + 0] +L0: + shrd eax, edx, cl + shr edx, cl + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm new file mode 100644 index 000000000..ef30e7f33 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RShiftU64.nasm +; +; Abstract: +; +; 64-bit logical right shift function for IA-32 +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathRShiftU64 ( +; IN UINT64 Operand, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathRShiftU64) +ASM_PFX(InternalMathRShiftU64): + mov cl, [esp + 12] ; cl <- Count + xor edx, edx + mov eax, [esp + 8] + test cl, 32 ; Count >= 32? + jnz .0 + mov edx, eax + mov eax, [esp + 4] +.0: + shrd eax, edx, cl + shr edx, cl + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm new file mode 100644 index 000000000..e12b8e961 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RdRand.nasm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 32-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + +SECTION .text + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + ; rdrand ax ; generate a 16 bit RN into ax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn16_ok: + mov edx, dword [esp + 4] + mov [edx], ax + mov eax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + ; rdrand eax ; generate a 32 bit RN into eax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn32_ok: + mov edx, dword [esp + 4] + mov [edx], eax + mov eax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand64 (UINT64 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + ; rdrand eax ; generate a 32 bit RN into eax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jnc rn64_ret ; jmp if CF=0 + mov edx, dword [esp + 4] + mov [edx], eax + + db 0xf, 0xc7, 0xf0 ; generate another 32 bit RN + jnc rn64_ret ; jmp if CF=0 + mov [edx + 4], eax + + mov eax, 1 + ret +rn64_ret: + xor eax, eax + ret ; return with failure status + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c new file mode 100644 index 000000000..4a37c7b02 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c @@ -0,0 +1,31 @@ +/** @file + AsmReadCr0 function + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + __asm { + mov eax, cr0 + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm new file mode 100644 index 000000000..8303313f2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr0.Asm +; +; Abstract: +; +; AsmReadCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr0) +ASM_PFX(AsmReadCr0): + mov eax, cr0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c new file mode 100644 index 000000000..feab38055 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c @@ -0,0 +1,32 @@ +/** @file + AsmReadCr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + __asm { + mov eax, cr2 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm new file mode 100644 index 000000000..202fb53ee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr2.Asm +; +; Abstract: +; +; AsmReadCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr2) +ASM_PFX(AsmReadCr2): + mov eax, cr2 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c new file mode 100644 index 000000000..b00e32491 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c @@ -0,0 +1,32 @@ +/** @file + AsmReadCr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + __asm { + mov eax, cr3 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm new file mode 100644 index 000000000..67b80ea9a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr3.Asm +; +; Abstract: +; +; AsmReadCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr3) +ASM_PFX(AsmReadCr3): + mov eax, cr3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c new file mode 100644 index 000000000..f948f82b7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c @@ -0,0 +1,34 @@ +/** @file + AsmReadCr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + __asm { + _emit 0x0f // mov eax, cr4 + _emit 0x20 + _emit 0xE0 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm new file mode 100644 index 000000000..8202da7c6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr4.Asm +; +; Abstract: +; +; AsmReadCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr4) +ASM_PFX(AsmReadCr4): + mov eax, cr4 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c new file mode 100644 index 000000000..02f23f5f1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadCs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, cs + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm new file mode 100644 index 000000000..8c2a3f08b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCs.Asm +; +; Abstract: +; +; AsmReadCs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadCs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCs) +ASM_PFX(AsmReadCs): + mov eax, cs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c new file mode 100644 index 000000000..5418f92a3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + __asm { + mov eax, dr0 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm new file mode 100644 index 000000000..ab700fc41 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr0.Asm +; +; Abstract: +; +; AsmReadDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr0) +ASM_PFX(AsmReadDr0): + mov eax, dr0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c new file mode 100644 index 000000000..d72adaadb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + __asm { + mov eax, dr1 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm new file mode 100644 index 000000000..594aa73a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr1.Asm +; +; Abstract: +; +; AsmReadDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr1) +ASM_PFX(AsmReadDr1): + mov eax, dr1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c new file mode 100644 index 000000000..fde799728 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + __asm { + mov eax, dr2 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm new file mode 100644 index 000000000..ec7eb5d47 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr2.Asm +; +; Abstract: +; +; AsmReadDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr2) +ASM_PFX(AsmReadDr2): + mov eax, dr2 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c new file mode 100644 index 000000000..9b899e79c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + __asm { + mov eax, dr3 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm new file mode 100644 index 000000000..9e79ef6e1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr3.Asm +; +; Abstract: +; +; AsmReadDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr3) +ASM_PFX(AsmReadDr3): + mov eax, dr3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c new file mode 100644 index 000000000..52293d335 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c @@ -0,0 +1,34 @@ +/** @file + AsmReadDr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + __asm { + _emit 0x0f + _emit 0x21 + _emit 0xe0 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm new file mode 100644 index 000000000..81c681de3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr4.Asm +; +; Abstract: +; +; AsmReadDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr4) +ASM_PFX(AsmReadDr4): + ; + ; DR4 is alias to DR6 only if DE (in CR4) is cleared. Otherwise, reading + ; this register will cause a #UD exception. + ; + ; MS assembler doesn't support this instruction since no one would use it + ; under normal circustances. Here opcode is used. + ; + DB 0xf, 0x21, 0xe0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c new file mode 100644 index 000000000..ecf6dc2d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c @@ -0,0 +1,34 @@ +/** @file + AsmReadDr5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + __asm { + _emit 0x0f + _emit 0x21 + _emit 0xe8 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm new file mode 100644 index 000000000..e2deacb83 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr5.Asm +; +; Abstract: +; +; AsmReadDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr5) +ASM_PFX(AsmReadDr5): + ; + ; DR5 is alias to DR7 only if DE (in CR4) is cleared. Otherwise, reading + ; this register will cause a #UD exception. + ; + ; MS assembler doesn't support this instruction since no one would use it + ; under normal circustances. Here opcode is used. + ; + DB 0xf, 0x21, 0xe8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c new file mode 100644 index 000000000..2b082970f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + __asm { + mov eax, dr6 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm new file mode 100644 index 000000000..a3e38aa11 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr6.Asm +; +; Abstract: +; +; AsmReadDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr6) +ASM_PFX(AsmReadDr6): + mov eax, dr6 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c new file mode 100644 index 000000000..8be80482f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDr7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + __asm { + mov eax, dr7 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm new file mode 100644 index 000000000..6cbbb484e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr7.Asm +; +; Abstract: +; +; AsmReadDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr7) +ASM_PFX(AsmReadDr7): + mov eax, dr7 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c new file mode 100644 index 000000000..3cdada3ac --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadDs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, ds + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm new file mode 100644 index 000000000..e2d3a05ec --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDs.Asm +; +; Abstract: +; +; AsmReadDs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadDs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDs) +ASM_PFX(AsmReadDs): + mov eax, ds + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c new file mode 100644 index 000000000..1cea323c5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c @@ -0,0 +1,33 @@ +/** @file + AsmReadEflags function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and x64. This returns a 32-bit value on IA-32 and a + 64-bit value on x64. + + @return EFLAGS on IA-32 or RFLAGS on x64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ) +{ + __asm { + pushfd + pop eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm new file mode 100644 index 000000000..05dca3fa6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadEflags.Asm +; +; Abstract: +; +; AsmReadEflags function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadEflags ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadEflags) +ASM_PFX(AsmReadEflags): + pushfd + pop eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c new file mode 100644 index 000000000..30953fdf3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadEs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of ES Data Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, es + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm new file mode 100644 index 000000000..5228298cf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadEs.Asm +; +; Abstract: +; +; AsmReadEs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadEs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadEs) +ASM_PFX(AsmReadEs): + mov eax, es + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c new file mode 100644 index 000000000..51fb020b1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadFs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, fs + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm new file mode 100644 index 000000000..fa7fbc351 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadFs.Asm +; +; Abstract: +; +; AsmReadFs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadFs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadFs) +ASM_PFX(AsmReadFs): + mov eax, fs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c new file mode 100644 index 000000000..5b01300b4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c @@ -0,0 +1,33 @@ +/** @file + AsmReadGdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + _asm { + mov eax, Gdtr + sgdt fword ptr [eax] + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm new file mode 100644 index 000000000..03b03a89b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadGdtr.Asm +; +; Abstract: +; +; AsmReadGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86ReadGdtr ( +; OUT IA32_DESCRIPTOR *Gdtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86ReadGdtr) +ASM_PFX(InternalX86ReadGdtr): + mov eax, [esp + 4] + sgdt [eax] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c new file mode 100644 index 000000000..6209a31ae --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadGs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, gs + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm new file mode 100644 index 000000000..b1e46deef --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadGs.Asm +; +; Abstract: +; +; AsmReadGs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadGs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadGs) +ASM_PFX(AsmReadGs): + mov eax, gs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c new file mode 100644 index 000000000..93f44535d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c @@ -0,0 +1,32 @@ +/** @file + AsmReadIdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + _asm { + mov eax, Idtr + sidt fword ptr [eax] + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm new file mode 100644 index 000000000..9fa1c62e3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadIdtr.Asm +; +; Abstract: +; +; AsmReadIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86ReadIdtr ( +; OUT IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86ReadIdtr) +ASM_PFX(InternalX86ReadIdtr): + mov eax, [esp + 4] + sidt [eax] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c new file mode 100644 index 000000000..407676a46 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c @@ -0,0 +1,31 @@ +/** @file + AsmReadLdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and x64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ) +{ + _asm { + sldt ax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm new file mode 100644 index 000000000..c1e169b65 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadLdtr.Asm +; +; Abstract: +; +; AsmReadLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadLdtr ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadLdtr) +ASM_PFX(AsmReadLdtr): + sldt ax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c new file mode 100644 index 000000000..00dfe0589 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and x64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm0 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm new file mode 100644 index 000000000..36da46f43 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm0.Asm +; +; Abstract: +; +; AsmReadMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm0) +ASM_PFX(AsmReadMm0): + push eax + push eax + movq [esp], mm0 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c new file mode 100644 index 000000000..0ed311e41 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and x64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm1 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm new file mode 100644 index 000000000..49ae74264 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm1.Asm +; +; Abstract: +; +; AsmReadMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm1) +ASM_PFX(AsmReadMm1): + push eax + push eax + movq [esp], mm1 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c new file mode 100644 index 000000000..bd830c557 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and x64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm2 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm new file mode 100644 index 000000000..3023592a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm2.Asm +; +; Abstract: +; +; AsmReadMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm2) +ASM_PFX(AsmReadMm2): + push eax + push eax + movq [esp], mm2 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c new file mode 100644 index 000000000..c8967083b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and x64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm3 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm new file mode 100644 index 000000000..339468cc0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm3.Asm +; +; Abstract: +; +; AsmReadMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm3) +ASM_PFX(AsmReadMm3): + push eax + push eax + movq [esp], mm3 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c new file mode 100644 index 000000000..9e2794cd4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and x64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm4 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm new file mode 100644 index 000000000..53da33a3f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm4.Asm +; +; Abstract: +; +; AsmReadMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm4) +ASM_PFX(AsmReadMm4): + push eax + push eax + movq [esp], mm4 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c new file mode 100644 index 000000000..93cad05a4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and x64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm5 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm new file mode 100644 index 000000000..dd1e87cf8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm5.Asm +; +; Abstract: +; +; AsmReadMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm5) +ASM_PFX(AsmReadMm5): + push eax + push eax + movq [esp], mm5 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c new file mode 100644 index 000000000..d2c559163 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and x64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm6 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm new file mode 100644 index 000000000..1b43d056e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm6.Asm +; +; Abstract: +; +; AsmReadMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm6) +ASM_PFX(AsmReadMm6): + push eax + push eax + movq [esp], mm6 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c new file mode 100644 index 000000000..68cf03928 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c @@ -0,0 +1,36 @@ +/** @file + AsmReadMm7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and x64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ) +{ + _asm { + push eax + push eax + movq [esp], mm7 + pop eax + pop edx + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm new file mode 100644 index 000000000..3df4c9fc8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm7.Asm +; +; Abstract: +; +; AsmReadMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm7) +ASM_PFX(AsmReadMm7): + push eax + push eax + movq [esp], mm7 + pop eax + pop edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c new file mode 100644 index 000000000..6d2394b1a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c @@ -0,0 +1,37 @@ +/** @file + AsmReadMsr64 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + _asm { + mov ecx, Index + rdmsr + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm new file mode 100644 index 000000000..97b853a3a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMsr64.Asm +; +; Abstract: +; +; AsmReadMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMsr64 ( +; IN UINT64 Index +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMsr64) +ASM_PFX(AsmReadMsr64): + mov ecx, [esp + 4] + rdmsr + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c new file mode 100644 index 000000000..cc09ed700 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c @@ -0,0 +1,31 @@ +/** @file + AsmReadPmc function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and x64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ) +{ + _asm { + mov ecx, Index + rdpmc + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm new file mode 100644 index 000000000..53142e33f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadPmc.Asm +; +; Abstract: +; +; AsmReadPmc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadPmc ( +; IN UINT32 PmcIndex +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadPmc) +ASM_PFX(AsmReadPmc): + mov ecx, [esp + 4] + rdpmc + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c new file mode 100644 index 000000000..9d7a6411a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c @@ -0,0 +1,32 @@ +/** @file + AsmReadSs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + __asm { + xor eax, eax + mov ax, ss + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm new file mode 100644 index 000000000..61628dec3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadSs.Asm +; +; Abstract: +; +; AsmReadSs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadSs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadSs) +ASM_PFX(AsmReadSs): + mov eax, ss + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c new file mode 100644 index 000000000..b52f8f31d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c @@ -0,0 +1,31 @@ +/** @file + AsmReadTr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + _asm { + str ax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm new file mode 100644 index 000000000..9f238e2ae --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTr.Asm +; +; Abstract: +; +; AsmReadTr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadTr ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTr) +ASM_PFX(AsmReadTr): + str ax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c new file mode 100644 index 000000000..a67b57a77 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c @@ -0,0 +1,31 @@ +/** @file + AsmReadTsc function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and x64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ) +{ + _asm { + rdtsc + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm new file mode 100644 index 000000000..1bc875bd3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTsc) +ASM_PFX(AsmReadTsc): + rdtsc + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm new file mode 100644 index 000000000..364613b5f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetJump.Asm +; +; Abstract: +; +; Implementation of SetJump() on IA-32. +; +;------------------------------------------------------------------------------ + +%include "Nasm.inc" + + SECTION .text + +extern ASM_PFX(InternalAssertJumpBuffer) +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; SetJump ( +; OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(SetJump) +ASM_PFX(SetJump): + push DWORD [esp + 4] + call ASM_PFX(InternalAssertJumpBuffer) ; To validate JumpBuffer + pop ecx + pop ecx ; ecx <- return address + mov edx, [esp] + + xor eax, eax + mov [edx + 24], eax ; save 0 to SSP + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov eax, 1 + INCSSP_EAX ; to read original SSP + READSSP_EAX + mov [edx + 0x24], eax ; save SSP + +CetDone: + + mov [edx], ebx + mov [edx + 4], esi + mov [edx + 8], edi + mov [edx + 12], ebp + mov [edx + 16], esp + mov [edx + 20], ecx ; eip value to restore in LongJump + xor eax, eax + jmp ecx + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c new file mode 100644 index 000000000..67587f1d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c @@ -0,0 +1,37 @@ +/** @file + Implementation of 64-bit swap bytes + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ) +{ + _asm { + mov eax, dword ptr [Operand + 4] + mov edx, dword ptr [Operand + 0] + bswap eax + bswap edx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm new file mode 100644 index 000000000..73a109415 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalMathSwapBytes64 ( +; IN UINT64 Operand +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMathSwapBytes64) +ASM_PFX(InternalMathSwapBytes64): + mov eax, [esp + 8] ; eax <- upper 32 bits + mov edx, [esp + 4] ; edx <- lower 32 bits + bswap eax + bswap edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm new file mode 100644 index 000000000..03a300dc6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm @@ -0,0 +1,257 @@ + +#include "BaseLibInternals.h" + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Thunk.asm +; +; Abstract: +; +; Real mode thunk +; +;------------------------------------------------------------------------------ + +global ASM_PFX(m16Size) +global ASM_PFX(mThunk16Attr) +global ASM_PFX(m16Gdt) +global ASM_PFX(m16GdtrBase) +global ASM_PFX(mTransition) +global ASM_PFX(m16Start) + +struc IA32_REGS + + ._EDI: resd 1 + ._ESI: resd 1 + ._EBP: resd 1 + ._ESP: resd 1 + ._EBX: resd 1 + ._EDX: resd 1 + ._ECX: resd 1 + ._EAX: resd 1 + ._DS: resw 1 + ._ES: resw 1 + ._FS: resw 1 + ._GS: resw 1 + ._EFLAGS: resd 1 + ._EIP: resd 1 + ._CS: resw 1 + ._SS: resw 1 + .size: + +endstruc + +;; .const + +SECTION .data + +; +; These are global constant to convey information to C code. +; +ASM_PFX(m16Size) DW ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) +ASM_PFX(mThunk16Attr) DW _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start) +ASM_PFX(m16Gdt) DW _NullSegDesc - ASM_PFX(m16Start) +ASM_PFX(m16GdtrBase) DW _16GdtrBase - ASM_PFX(m16Start) +ASM_PFX(mTransition) DW _EntryPoint - ASM_PFX(m16Start) + +SECTION .text + +ASM_PFX(m16Start): + +SavedGdt: + dw 0 + dd 0 + +;------------------------------------------------------------------------------ +; _BackFromUserCode() takes control in real mode after 'retf' has been executed +; by user code. It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_BackFromUserCode: + ; + ; The order of saved registers on the stack matches the order they appears + ; in IA32_REGS structure. This facilitates wrapper function to extract them + ; into that structure. + ; +BITS 16 + push ss + push cs + ; + ; Note: We can't use o32 on the next instruction because of a bug + ; in NASM 2.09.04 through 2.10rc1. + ; + call dword .Base ; push eip +.Base: + pushfd + cli ; disable interrupts + push gs + push fs + push es + push ds + pushad + mov edx, strict dword 0 +.ThunkAttrEnd: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 + jz .1 + mov ax, 2401h + int 15h + cli ; disable interrupts + jnc .2 +.1: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL + jz .2 + in al, 92h + or al, 2 + out 92h, al ; deactivate A20M# +.2: + xor eax, eax + mov ax, ss + lea ebp, [esp + IA32_REGS.size] + mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp + mov bx, [bp - IA32_REGS.size + IA32_REGS._EIP] + shl eax, 4 ; shl eax, 4 + add ebp, eax ; add ebp, eax + mov eax, strict dword 0 +.SavedCr4End: + mov cr4, eax +o32 lgdt [cs:bx + (SavedGdt - .Base)] + mov eax, strict dword 0 +.SavedCr0End: + mov cr0, eax + mov ax, strict word 0 +.SavedSsEnd: + mov ss, eax + mov esp, strict dword 0 +.SavedEspEnd: +o32 retf ; return to protected mode + +_EntryPoint: + DD _ToUserCode - ASM_PFX(m16Start) + DW 8h +_16Idtr: + DW (1 << 10) - 1 + DD 0 +_16Gdtr: + DW GdtEnd - _NullSegDesc - 1 +_16GdtrBase: + DD 0 + +;------------------------------------------------------------------------------ +; _ToUserCode() takes control in real mode before passing control to user code. +; It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_ToUserCode: +BITS 16 + mov dx, ss + mov ss, cx ; set new segment selectors + mov ds, cx + mov es, cx + mov fs, cx + mov gs, cx + mov cr0, eax ; real mode starts at next instruction + ; which (per SDM) *must* be a far JMP. + jmp 0:strict word 0 +.RealAddrEnd: + mov cr4, ebp + mov ss, si ; set up 16-bit stack segment + xchg esp, ebx ; set up 16-bit stack pointer + mov bp, [esp + IA32_REGS.size] + mov [cs:bp + (_BackFromUserCode.SavedSsEnd - 2 - _BackFromUserCode)], dx + mov [cs:bp + (_BackFromUserCode.SavedEspEnd - 4 - _BackFromUserCode)], ebx + lidt [cs:bp + (_16Idtr - _BackFromUserCode)] + + popad + pop ds + pop es + pop fs + pop gs + popfd + +o32 retf ; transfer control to user code + +ALIGN 16 +_NullSegDesc DQ 0 +_16CsDesc: + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_16DsDesc: + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +GdtEnd: + +;------------------------------------------------------------------------------ +; IA32_REGISTER_SET * +; EFIAPI +; InternalAsmThunk16 ( +; IN IA32_REGISTER_SET *RegisterSet, +; IN OUT VOID *Transition +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalAsmThunk16) +ASM_PFX(InternalAsmThunk16): +BITS 32 + push ebp + push ebx + push esi + push edi + push ds + push es + push fs + push gs + mov esi, [esp + 36] ; esi <- RegSet, the 1st parameter + movzx edx, word [esi + IA32_REGS._SS] + mov edi, [esi + IA32_REGS._ESP] + add edi, - (IA32_REGS.size + 4) ; reserve stack space + mov ebx, edi ; ebx <- stack offset + imul eax, edx, 16 ; eax <- edx * 16 + push IA32_REGS.size / 4 + add edi, eax ; edi <- linear address of 16-bit stack + pop ecx + rep movsd ; copy RegSet + mov eax, [esp + 40] ; eax <- address of transition code + mov esi, edx ; esi <- 16-bit stack segment + lea edx, [eax + (_BackFromUserCode.SavedCr0End - ASM_PFX(m16Start))] + mov ecx, eax + and ecx, 0fh + shl eax, 12 + lea ecx, [ecx + (_BackFromUserCode - ASM_PFX(m16Start))] + mov ax, cx + stosd ; [edi] <- return address of user code + add eax, _ToUserCode.RealAddrEnd - _BackFromUserCode + mov [edx + (_ToUserCode.RealAddrEnd - 4 - _BackFromUserCode.SavedCr0End)], eax + sgdt [edx + (SavedGdt - _BackFromUserCode.SavedCr0End)] + sidt [esp + 36] ; save IDT stack in argument space + mov eax, cr0 + mov [edx - 4], eax ; save CR0 in _BackFromUserCode.SavedCr0End - 4 + and eax, 7ffffffeh ; clear PE, PG bits + mov ebp, cr4 + mov [edx + (_BackFromUserCode.SavedCr4End - 4 - _BackFromUserCode.SavedCr0End)], ebp + and ebp, ~30h ; clear PAE, PSE bits + push 10h + pop ecx ; ecx <- selector for data segments + lgdt [edx + (_16Gdtr - _BackFromUserCode.SavedCr0End)] + pushfd ; Save df/if indeed + call dword far [edx + (_EntryPoint - _BackFromUserCode.SavedCr0End)] + popfd + lidt [esp + 36] ; restore protected mode IDTR + lea eax, [ebp - IA32_REGS.size] ; eax <- the address of IA32_REGS + pop gs + pop fs + pop es + pop ds + pop edi + pop esi + pop ebx + pop ebp + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm new file mode 100644 index 000000000..69f7fbf35 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; VmgExit.Asm +; +; Abstract: +; +; AsmVmgExit function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmVmgExit ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmVmgExit) +ASM_PFX(AsmVmgExit): +; +; NASM doesn't support the vmmcall instruction in 32-bit mode and NASM versions +; before 2.12 cannot translate the 64-bit "rep vmmcall" instruction into elf32 +; format. Given that VMGEXIT does not make sense on IA32, provide a stub +; implementation that is identical to CpuBreakpoint(). In practice, AsmVmgExit() +; should never be called on IA32. +; + int 3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c new file mode 100644 index 000000000..87bd71f05 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c @@ -0,0 +1,29 @@ +/** @file + AsmWbinvd function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ) +{ + _asm { + wbinvd + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm new file mode 100644 index 000000000..714e42789 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Wbinvd.Asm +; +; Abstract: +; +; AsmWbinvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWbinvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWbinvd) +ASM_PFX(AsmWbinvd): + wbinvd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c new file mode 100644 index 000000000..46e49a678 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteCr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Value + ) +{ + _asm { + mov eax, Value + mov cr0, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm new file mode 100644 index 000000000..6730fbe37 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr0.Asm +; +; Abstract: +; +; AsmWriteCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr0 ( +; UINTN Cr0 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr0) +ASM_PFX(AsmWriteCr0): + mov eax, [esp + 4] + mov cr0, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c new file mode 100644 index 000000000..f437bfc8c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteCr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Value + ) +{ + _asm { + mov eax, Value + mov cr2, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm new file mode 100644 index 000000000..989639066 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr2.Asm +; +; Abstract: +; +; AsmWriteCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr2 ( +; UINTN Cr2 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr2) +ASM_PFX(AsmWriteCr2): + mov eax, [esp + 4] + mov cr2, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c new file mode 100644 index 000000000..48cb8ad16 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteCr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Value + ) +{ + _asm { + mov eax, Value + mov cr3, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm new file mode 100644 index 000000000..21114f35c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr3.Asm +; +; Abstract: +; +; AsmWriteCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr3 ( +; UINTN Cr3 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr3) +ASM_PFX(AsmWriteCr3): + mov eax, [esp + 4] + mov cr3, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c new file mode 100644 index 000000000..01f059ffa --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c @@ -0,0 +1,33 @@ +/** @file + AsmWriteCr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Value + ) +{ + _asm { + mov eax, Value + _emit 0x0f // mov cr4, eax + _emit 0x22 + _emit 0xE0 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm new file mode 100644 index 000000000..b090606b1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr4.Asm +; +; Abstract: +; +; AsmWriteCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr4 ( +; UINTN Cr4 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr4) +ASM_PFX(AsmWriteCr4): + mov eax, [esp + 4] + mov cr4, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c new file mode 100644 index 000000000..80bb23818 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr0, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm new file mode 100644 index 000000000..24cd2c2e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr0.Asm +; +; Abstract: +; +; AsmWriteDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr0 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr0) +ASM_PFX(AsmWriteDr0): + mov eax, [esp + 4] + mov dr0, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c new file mode 100644 index 000000000..f1c8f325e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr1, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm new file mode 100644 index 000000000..57afac4f1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr1.Asm +; +; Abstract: +; +; AsmWriteDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr1 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr1) +ASM_PFX(AsmWriteDr1): + mov eax, [esp + 4] + mov dr1, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c new file mode 100644 index 000000000..6e1e7f240 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr2, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm new file mode 100644 index 000000000..3fd32a772 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr2.Asm +; +; Abstract: +; +; AsmWriteDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr2 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr2) +ASM_PFX(AsmWriteDr2): + mov eax, [esp + 4] + mov dr2, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c new file mode 100644 index 000000000..7cb1d3724 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr3, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm new file mode 100644 index 000000000..73ad24a8c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr3.Asm +; +; Abstract: +; +; AsmWriteDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr3 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr3) +ASM_PFX(AsmWriteDr3): + mov eax, [esp + 4] + mov dr3, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c new file mode 100644 index 000000000..778017f33 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c @@ -0,0 +1,33 @@ +/** @file + AsmWriteDr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + _emit 0x0f // mov dr4, eax + _emit 0x23 + _emit 0xe0 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm new file mode 100644 index 000000000..0d23fca11 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr4.Asm +; +; Abstract: +; +; AsmWriteDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr4 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr4) +ASM_PFX(AsmWriteDr4): + mov eax, [esp + 4] + ; + ; DR4 is alias to DR6 only if DE (in CR4) is cleared. Otherwise, writing to + ; this register will cause a #UD exception. + ; + ; MS assembler doesn't support this instruction since no one would use it + ; under normal circustances. Here opcode is used. + ; + DB 0xf, 0x23, 0xe0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c new file mode 100644 index 000000000..2159813a3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c @@ -0,0 +1,33 @@ +/** @file + AsmWriteDr5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + _emit 0x0f // mov dr5, eax + _emit 0x23 + _emit 0xe8 + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm new file mode 100644 index 000000000..bc5f424b8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr5.Asm +; +; Abstract: +; +; AsmWriteDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr5 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr5) +ASM_PFX(AsmWriteDr5): + mov eax, [esp + 4] + ; + ; DR5 is alias to DR7 only if DE (in CR4) is cleared. Otherwise, writing to + ; this register will cause a #UD exception. + ; + ; MS assembler doesn't support this instruction since no one would use it + ; under normal circustances. Here opcode is used. + ; + DB 0xf, 0x23, 0xe8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c new file mode 100644 index 000000000..c03d71643 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr6, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm new file mode 100644 index 000000000..9089c52c9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr6.Asm +; +; Abstract: +; +; AsmWriteDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr6 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr6) +ASM_PFX(AsmWriteDr6): + mov eax, [esp + 4] + mov dr6, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c new file mode 100644 index 000000000..c4821e4cd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteDr7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Value The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + IN UINTN Value + ) +{ + _asm { + mov eax, Value + mov dr7, eax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm new file mode 100644 index 000000000..5dc22b695 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr7.Asm +; +; Abstract: +; +; AsmWriteDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr7 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr7) +ASM_PFX(AsmWriteDr7): + mov eax, [esp + 4] + mov dr7, eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c new file mode 100644 index 000000000..37ceae73f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c @@ -0,0 +1,33 @@ +/** @file + AsmWriteGdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + _asm { + mov eax, Gdtr + lgdt fword ptr [eax] + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm new file mode 100644 index 000000000..cc1a08a53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteGdtr.Asm +; +; Abstract: +; +; AsmWriteGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86WriteGdtr ( +; IN CONST IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86WriteGdtr) +ASM_PFX(InternalX86WriteGdtr): + mov eax, [esp + 4] + lgdt [eax] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c new file mode 100644 index 000000000..49ef22b99 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c @@ -0,0 +1,35 @@ +/** @file + AsmWriteIdtr function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + _asm { + mov eax, Idtr + pushfd + cli + lidt fword ptr [eax] + popfd + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm new file mode 100644 index 000000000..074dc1846 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteIdtr.Asm +; +; Abstract: +; +; AsmWriteIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86WriteIdtr ( +; IN CONST IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86WriteIdtr) +ASM_PFX(InternalX86WriteIdtr): + mov eax, [esp + 4] + pushfd + cli + lidt [eax] + popfd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c new file mode 100644 index 000000000..8e12f7840 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c @@ -0,0 +1,33 @@ +/** @file + AsmWriteLdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current Local Descriptor Table Register (GDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and x64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + _asm { + xor eax, eax + mov ax, Ldtr + lldt ax + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm new file mode 100644 index 000000000..870ea18d7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteLdtr.Asm +; +; Abstract: +; +; AsmWriteLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteLdtr ( +; IN UINT16 Ldtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteLdtr) +ASM_PFX(AsmWriteLdtr): + mov eax, [esp + 4] + lldt ax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c new file mode 100644 index 000000000..ea26009a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ) +{ + _asm { + movq mm0, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm new file mode 100644 index 000000000..4fcf9da85 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm0.Asm +; +; Abstract: +; +; AsmWriteMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm0 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm0) +ASM_PFX(AsmWriteMm0): + movq mm0, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c new file mode 100644 index 000000000..b8da47329 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ) +{ + _asm { + movq mm1, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm new file mode 100644 index 000000000..00e2d10b9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm1.Asm +; +; Abstract: +; +; AsmWriteMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm1 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm1) +ASM_PFX(AsmWriteMm1): + movq mm1, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c new file mode 100644 index 000000000..6b77aed7a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ) +{ + _asm { + movq mm2, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm new file mode 100644 index 000000000..ec9d2b299 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm2.Asm +; +; Abstract: +; +; AsmWriteMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm2 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm2) +ASM_PFX(AsmWriteMm2): + movq mm2, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c new file mode 100644 index 000000000..4fc7d7042 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ) +{ + _asm { + movq mm3, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm new file mode 100644 index 000000000..01d29c49a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm3.Asm +; +; Abstract: +; +; AsmWriteMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm3 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm3) +ASM_PFX(AsmWriteMm3): + movq mm3, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c new file mode 100644 index 000000000..2fce55497 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteMm4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ) +{ + _asm { + movq mm4, qword ptr [Value] + emms + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm new file mode 100644 index 000000000..0b2255655 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm4.Asm +; +; Abstract: +; +; AsmWriteMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm4 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm4) +ASM_PFX(AsmWriteMm4): + movq mm4, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c new file mode 100644 index 000000000..a0ec714e3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c @@ -0,0 +1,31 @@ +/** @file + AsmWriteMm5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ) +{ + _asm { + movq mm5, qword ptr [Value] + emms + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm new file mode 100644 index 000000000..4a3c0df48 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm5.Asm +; +; Abstract: +; +; AsmWriteMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm5 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm5) +ASM_PFX(AsmWriteMm5): + movq mm5, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c new file mode 100644 index 000000000..c3b57b4b5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ) +{ + _asm { + movq mm6, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm new file mode 100644 index 000000000..397ccfbc2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm6.Asm +; +; Abstract: +; +; AsmWriteMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm6 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm6) +ASM_PFX(AsmWriteMm6): + movq mm6, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c new file mode 100644 index 000000000..e1e893245 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c @@ -0,0 +1,32 @@ +/** @file + AsmWriteMm7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ) +{ + _asm { + movq mm7, qword ptr [Value] + emms + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm new file mode 100644 index 000000000..ee3c7f1d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm7.Asm +; +; Abstract: +; +; AsmWriteMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm7 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm7) +ASM_PFX(AsmWriteMm7): + movq mm7, [esp + 4] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c new file mode 100644 index 000000000..badf1d8e5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c @@ -0,0 +1,43 @@ +/** @file + AsmWriteMsr64 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + _asm { + mov edx, dword ptr [Value + 4] + mov eax, dword ptr [Value + 0] + mov ecx, Index + wrmsr + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm new file mode 100644 index 000000000..f9e3b0561 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMsr64.Asm +; +; Abstract: +; +; AsmWriteMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMsr64 ( +; IN UINT32 Index, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMsr64) +ASM_PFX(AsmWriteMsr64): + mov edx, [esp + 12] + mov eax, [esp + 8] + mov ecx, [esp + 4] + wrmsr + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm new file mode 100644 index 000000000..e36c63863 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm @@ -0,0 +1,30 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2017, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteTr.nasm +; +; Abstract: +; +; Write TR register +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; AsmWriteTr ( +; UINT16 Selector +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteTr) +ASM_PFX(AsmWriteTr): + mov eax, [esp+4] + ltr ax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm b/roms/edk2/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm new file mode 100644 index 000000000..9f7b03bbf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; XGetBv.Asm +; +; Abstract: +; +; AsmXgetBv function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmXGetBv ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmXGetBv) +ASM_PFX(AsmXGetBv): + mov ecx, [esp + 4] + xgetbv + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/LRotU32.c b/roms/edk2/MdePkg/Library/BaseLib/LRotU32.c new file mode 100644 index 000000000..4e671a320 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LRotU32.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 32); + return (Operand << Count) | (Operand >> (32 - Count)); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LRotU64.c b/roms/edk2/MdePkg/Library/BaseLib/LRotU64.c new file mode 100644 index 000000000..48f35dc63 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LRotU64.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathLRotU64 (Operand, Count); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/LShiftU64.c new file mode 100644 index 000000000..7b41a3efb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LShiftU64.c @@ -0,0 +1,35 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathLShiftU64 (Operand, Count); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LinkedList.c b/roms/edk2/MdePkg/Library/BaseLib/LinkedList.c new file mode 100644 index 000000000..5648c1877 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LinkedList.c @@ -0,0 +1,599 @@ +/** @file + Linked List Library Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + If PcdVerifyNodeInList is TRUE, ASSERTs when SecondEntry is or is not part of + the same doubly-linked list as FirstEntry depending on the value of InList. + Independent of PcdVerifyNodeInList, ASSERTs when FirstEntry is not part of a + valid list. + + If FirstEntry is NULL, then ASSERT(). + If FirstEntry->ForwardLink is NULL, then ASSERT(). + If FirstEntry->BackLink is NULL, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and SecondEntry is NULL, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to the node to locate. + @param InList Defines whether to check if SecondEntry is or is not part + of the same doubly-linked list as FirstEntry. + +**/ +#if !defined (MDEPKG_NDEBUG) + #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList) \ + do { \ + if (FeaturePcdGet (PcdVerifyNodeInList)) { \ + ASSERT (InList == IsNodeInList ((FirstEntry), (SecondEntry))); \ + } else { \ + ASSERT (InternalBaseLibIsListValid (FirstEntry)); \ + } \ + } while (FALSE) +#else + #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList) +#endif + +/** + Worker function that verifies the validity of this list. + + If List is NULL, then ASSERT(). + If List->ForwardLink is NULL, then ASSERT(). + If List->BackLink is NULL, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + + @param List A pointer to a node in a linked list. + + @retval TRUE if PcdVerifyNodeInList is FALSE + @retval TRUE if DoMembershipCheck is FALSE + @retval TRUE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE + and Node is a member of List. + @retval FALSE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE + and Node is in not a member of List. + +**/ +BOOLEAN +EFIAPI +InternalBaseLibIsListValid ( + IN CONST LIST_ENTRY *List + ) +{ + UINTN Count; + CONST LIST_ENTRY *Ptr; + + // + // Test the validity of List and Node + // + ASSERT (List != NULL); + ASSERT (List->ForwardLink != NULL); + ASSERT (List->BackLink != NULL); + + if (PcdGet32 (PcdMaximumLinkedListLength) > 0) { + Count = 0; + Ptr = List; + + // + // Count the total number of nodes in List. + // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength + // + do { + Ptr = Ptr->ForwardLink; + Count++; + } while ((Ptr != List) && (Count < PcdGet32 (PcdMaximumLinkedListLength))); + + // + // return whether linked list is too long + // + return (BOOLEAN)(Count < PcdGet32 (PcdMaximumLinkedListLength)); + } + + return TRUE; +} + +/** + Checks whether FirstEntry and SecondEntry are part of the same doubly-linked + list. + + If FirstEntry is NULL, then ASSERT(). + If FirstEntry->ForwardLink is NULL, then ASSERT(). + If FirstEntry->BackLink is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(); + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to the node to locate. + + @retval TRUE SecondEntry is in the same doubly-linked list as FirstEntry. + @retval FALSE SecondEntry isn't in the same doubly-linked list as FirstEntry, + or FirstEntry is invalid. + +**/ +BOOLEAN +EFIAPI +IsNodeInList ( + IN CONST LIST_ENTRY *FirstEntry, + IN CONST LIST_ENTRY *SecondEntry + ) +{ + UINTN Count; + CONST LIST_ENTRY *Ptr; + + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (FirstEntry)); + + ASSERT (SecondEntry != NULL); + + Count = 0; + Ptr = FirstEntry; + + // + // Check to see if SecondEntry is a member of FirstEntry. + // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength + // + do { + Ptr = Ptr->ForwardLink; + if (PcdGet32 (PcdMaximumLinkedListLength) > 0) { + Count++; + + // + // Return if the linked list is too long + // + if (Count == PcdGet32 (PcdMaximumLinkedListLength)) { + return (BOOLEAN)(Ptr == SecondEntry); + } + } + + if (Ptr == SecondEntry) { + return TRUE; + } + } while (Ptr != FirstEntry); + + return FALSE; +} + +/** + Initializes the head node of a doubly-linked list, and returns the pointer to + the head node of the doubly-linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN OUT LIST_ENTRY *ListHead + ) + +{ + ASSERT (ListHead != NULL); + + ListHead->ForwardLink = ListHead; + ListHead->BackLink = ListHead; + return ListHead; +} + +/** + Adds a node to the beginning of a doubly-linked list, and returns the pointer + to the head node of the doubly-linked list. + + Adds the node Entry at the beginning of the doubly-linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE); + + Entry->ForwardLink = ListHead->ForwardLink; + Entry->BackLink = ListHead; + Entry->ForwardLink->BackLink = Entry; + ListHead->ForwardLink = Entry; + return ListHead; +} + +/** + Adds a node to the end of a doubly-linked list, and returns the pointer to + the head node of the doubly-linked list. + + Adds the node Entry to the end of the doubly-linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE); + + Entry->ForwardLink = ListHead; + Entry->BackLink = ListHead->BackLink; + Entry->BackLink->ForwardLink = Entry; + ListHead->BackLink = Entry; + return ListHead; +} + +/** + Retrieves the first node of a doubly-linked list. + + Returns the first node of a doubly-linked list. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + + @return The first node of a doubly-linked list. + @retval List The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ) +{ + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (List)); + + return List->ForwardLink; +} + +/** + Retrieves the next node of a doubly-linked list. + + Returns the node of a doubly-linked list that follows Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @return A pointer to the next node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return Node->ForwardLink; +} + +/** + Retrieves the previous node of a doubly-linked list. + + Returns the node of a doubly-linked list that precedes Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @return A pointer to the previous node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetPreviousNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return Node->BackLink; +} + +/** + Checks to see if a doubly-linked list is empty or not. + + Checks to see if the doubly-linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *ListHead + ) +{ + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (ListHead)); + + return (BOOLEAN)(ListHead->ForwardLink == ListHead); +} + +/** + Determines if a node in a doubly-linked list is the head node of a the same + doubly-linked list. This function is typically used to terminate a loop that + traverses all the nodes in a doubly-linked list starting with the head node. + + Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the + nodes in the doubly-linked list specified by List. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), + then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not + equal to List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @retval TRUE Node is the head of the doubly-linked list pointed by List. + @retval FALSE Node is not the head of the doubly-linked list pointed by List. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return (BOOLEAN)(Node == List); +} + +/** + Determines if a node the last node in a doubly-linked list. + + Returns TRUE if Node is the last node in the doubly-linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node); +} + +/** + Swaps the location of two nodes in a doubly-linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly-linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + SecondEntry is returned after the nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If PcdVerifyNodeInList is TRUE and SecondEntry and FirstEntry are not in the + same linked list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing the FirstEntry and SecondEntry nodes, including + the FirstEntry and SecondEntry nodes, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + + @return SecondEntry. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN OUT LIST_ENTRY *FirstEntry, + IN OUT LIST_ENTRY *SecondEntry + ) +{ + LIST_ENTRY *Ptr; + + if (FirstEntry == SecondEntry) { + return SecondEntry; + } + + // + // ASSERT Entry1 and Entry2 are in the same linked list + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (FirstEntry, SecondEntry, TRUE); + + // + // Ptr is the node pointed to by FirstEntry->ForwardLink + // + Ptr = RemoveEntryList (FirstEntry); + + // + // If FirstEntry immediately follows SecondEntry, FirstEntry will be placed + // immediately in front of SecondEntry + // + if (Ptr->BackLink == SecondEntry) { + return InsertTailList (SecondEntry, FirstEntry); + } + + // + // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry, + // then there are no further steps necessary + // + if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) { + return Ptr; + } + + // + // Move SecondEntry to the front of Ptr + // + RemoveEntryList (SecondEntry); + InsertTailList (Ptr, SecondEntry); + return SecondEntry; +} + +/** + Removes a node from a doubly-linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly-linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly-linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing Entry, including the Entry node, is greater than + or equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param Entry A pointer to a node in a linked list. + + @return Entry. + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ) +{ + ASSERT (!IsListEmpty (Entry)); + + Entry->ForwardLink->BackLink = Entry->BackLink; + Entry->BackLink->ForwardLink = Entry->ForwardLink; + return Entry->ForwardLink; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LongJump.c b/roms/edk2/MdePkg/Library/BaseLib/LongJump.c new file mode 100644 index 000000000..1d88e4121 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LongJump.c @@ -0,0 +1,41 @@ +/** @file + Long Jump functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. This + function never returns to the caller. Instead is resumes execution based on + the state of JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + If Value is 0, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is + restored and must be non-zero. + +**/ +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ) +{ + InternalAssertJumpBuffer (JumpBuffer); + ASSERT (Value != 0); + + InternalLongJump (JumpBuffer, Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LowBitSet32.c b/roms/edk2/MdePkg/Library/BaseLib/LowBitSet32.c new file mode 100644 index 000000000..8383c7954 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LowBitSet32.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; 0 == (Operand & 1); BitIndex++, Operand >>= 1); + return BitIndex; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/LowBitSet64.c b/roms/edk2/MdePkg/Library/BaseLib/LowBitSet64.c new file mode 100644 index 000000000..349ed526b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/LowBitSet64.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; + (Operand & 1) == 0; + BitIndex++, Operand = RShiftU64 (Operand, 1)); + return BitIndex; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Math64.c b/roms/edk2/MdePkg/Library/BaseLib/Math64.c new file mode 100644 index 000000000..154b97ae7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Math64.c @@ -0,0 +1,362 @@ +/** @file + Leaf math worker functions that require 64-bit arithmetic support from the + compiler. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand << Count; +} + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand >> Count; +} + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits + are filled with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand arithmetically shifted right by Count. + +**/ +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + INTN TestValue; + + // + // Test if this compiler supports arithmetic shift + // + TestValue = (INTN)((INT64)(1ULL << 63) >> 63); + if (TestValue == -1) { + // + // Arithmetic shift is supported + // + return (UINT64)((INT64)Operand >> Count); + } + + // + // Arithmetic is not supported + // + return (Operand >> Count) | + ((INTN)Operand < 0 ? ~((UINTN)-1 >> Count) : 0); +} + + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling + the low bits with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count. + +**/ +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand << Count) | (Operand >> (64 - Count)); +} + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling + the high bits with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count. + +**/ +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand >> Count) | (Operand << (64 - Count)); +} + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swapped Operand. + +**/ +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ) +{ + UINT64 LowerBytes; + UINT64 HigherBytes; + + LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand); + HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32)); + + return (LowerBytes << 32 | HigherBytes); +} + +/** + Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return Dividend / Divisor; +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return (UINT32)(Dividend % Divisor); +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = (UINT32)(Dividend % Divisor); + } + return Dividend / Divisor; +} + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and + generates a 64-bit signed result and an optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit + signed value Divisor and generates a 64-bit signed quotient. If Remainder + is not NULL, then the 64-bit signed remainder is returned in Remainder. + This function returns the 64-bit signed quotient. + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/ModU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/ModU64x32.c new file mode 100644 index 000000000..ee99ab322 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/ModU64x32.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathModU64x32 (Dividend, Divisor); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/MultS64x64.c b/roms/edk2/MdePkg/Library/BaseLib/MultS64x64.c new file mode 100644 index 000000000..b5c745f7c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/MultS64x64.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Multiplies a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiplies the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier. + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ) +{ + return (INT64)MultU64x64 ((UINT64) Multiplicand, (UINT64) Multiplier); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/MultU64x32.c b/roms/edk2/MdePkg/Library/BaseLib/MultU64x32.c new file mode 100644 index 000000000..2bbff51c8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/MultU64x32.c @@ -0,0 +1,40 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x32 (Multiplicand, Multiplier); + + return Result; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/MultU64x64.c b/roms/edk2/MdePkg/Library/BaseLib/MultU64x64.c new file mode 100644 index 000000000..e1ee9f1c9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/MultU64x64.c @@ -0,0 +1,40 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x64 (Multiplicand, Multiplier); + + return Result; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RRotU32.c b/roms/edk2/MdePkg/Library/BaseLib/RRotU32.c new file mode 100644 index 000000000..3956faddd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RRotU32.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count. + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 32); + return (Operand >> Count) | (Operand << (32 - Count)); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RRotU64.c b/roms/edk2/MdePkg/Library/BaseLib/RRotU64.c new file mode 100644 index 000000000..e07ffd656 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RRotU64.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathRRotU64 (Operand, Count); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RShiftU64.c b/roms/edk2/MdePkg/Library/BaseLib/RShiftU64.c new file mode 100644 index 000000000..20f94f774 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RShiftU64.c @@ -0,0 +1,35 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathRShiftU64 (Operand, Count); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuBreakpoint.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuBreakpoint.c new file mode 100644 index 000000000..88d0877a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuBreakpoint.c @@ -0,0 +1,27 @@ +/** @file + CPU breakpoint for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +extern VOID RiscVCpuBreakpoint (VOID); + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + RiscVCpuBreakpoint (); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuPause.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuPause.c new file mode 100644 index 000000000..9931bad29 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/CpuPause.c @@ -0,0 +1,29 @@ +/** @file + CPU pause for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +extern VOID RiscVCpuPause (VOID); + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + RiscVCpuPause (); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/DisableInterrupts.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/DisableInterrupts.c new file mode 100644 index 000000000..867086c09 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/DisableInterrupts.c @@ -0,0 +1,24 @@ +/** @file + CPU disable interrupt function for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "BaseLibInternals.h" + +extern VOID RiscVDisableSupervisorModeInterrupts (VOID); + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + RiscVDisableSupervisorModeInterrupts (); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/EnableInterrupts.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/EnableInterrupts.c new file mode 100644 index 000000000..22ef73067 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/EnableInterrupts.c @@ -0,0 +1,25 @@ +/** @file + CPU enable interrupt function for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +extern VOID RiscVEnableSupervisorModeInterrupt (VOID); + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + RiscVEnableSupervisorModeInterrupt (); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/FlushCache.S b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/FlushCache.S new file mode 100644 index 000000000..7c10fdd26 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/FlushCache.S @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +// +// RISC-V cache operation. +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ + +.align 3 +ASM_GLOBAL ASM_PFX(RiscVInvalidateInstCacheAsm) +ASM_GLOBAL ASM_PFX(RiscVInvalidateDataCacheAsm) + +ASM_PFX(RiscVInvalidateInstCacheAsm): + fence.i + ret + +ASM_PFX(RiscVInvalidateDataCacheAsm): + fence + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/GetInterruptState.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/GetInterruptState.c new file mode 100644 index 000000000..292f1ec44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/GetInterruptState.c @@ -0,0 +1,35 @@ +/** @file + CPU get interrupt state function for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +extern UINT32 RiscVGetSupervisorModeInterrupts (VOID); + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE is interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + unsigned long RetValue; + + RetValue = RiscVGetSupervisorModeInterrupts (); + return RetValue? TRUE: FALSE; +} + + diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/InternalSwitchStack.c b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/InternalSwitchStack.c new file mode 100644 index 000000000..0bb292141 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/InternalSwitchStack.c @@ -0,0 +1,55 @@ +/** @file + Switch stack function for RISC-V + + Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. + Marker will be ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param Marker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +InternalSwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + IN VA_LIST Marker + ) +{ + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + DEBUG ((DEBUG_INFO, "RISC-V InternalSwitchStack Entry:%x Context1:%x Context2:%x NewStack%x\n", \ + EntryPoint, Context1, Context2, NewStack)); + JumpBuffer.RA = (UINTN)EntryPoint; + JumpBuffer.SP = (UINTN)NewStack - sizeof (VOID *); + JumpBuffer.S0 = (UINT64)(UINTN)Context1; + JumpBuffer.S1 = (UINT64)(UINTN)Context2; + LongJump (&JumpBuffer, (UINTN)-1); + ASSERT(FALSE); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuBreakpoint.S b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuBreakpoint.S new file mode 100644 index 000000000..ccf91df81 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuBreakpoint.S @@ -0,0 +1,14 @@ +//------------------------------------------------------------------------------ +// +// CpuBreakpoint for RISC-V +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(RiscVCpuBreakpoint) +ASM_PFX(RiscVCpuBreakpoint): + ebreak + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuPause.S b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuPause.S new file mode 100644 index 000000000..6660c2fcb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVCpuPause.S @@ -0,0 +1,14 @@ +//------------------------------------------------------------------------------ +// +// CpuPause for RISC-V +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(RiscVCpuPause) +ASM_PFX(RiscVCpuPause): + nop + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S new file mode 100644 index 000000000..87b3468fc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// RISC-V Supervisor Mode interrupt enable/disable +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(RiscVDisableSupervisorModeInterrupts) +ASM_GLOBAL ASM_PFX(RiscVEnableSupervisorModeInterrupt) +ASM_GLOBAL ASM_PFX(RiscVGetSupervisorModeInterrupts) + +#define SSTATUS_SIE 0x00000002 +#define CSR_SSTATUS 0x100 + #define SSTATUS_SPP_BIT_POSITION 8 + +// +// This routine disables supervisor mode interrupt +// +ASM_PFX(RiscVDisableSupervisorModeInterrupts): + add sp, sp, -(__SIZEOF_POINTER__) + sd a1, (sp) + li a1, SSTATUS_SIE + csrc CSR_SSTATUS, a1 + ld a1, (sp) + add sp, sp, (__SIZEOF_POINTER__) + ret + +// +// This routine enables supervisor mode interrupt +// +ASM_PFX(RiscVEnableSupervisorModeInterrupt): + add sp, sp, -2*(__SIZEOF_POINTER__) + sd a0, (0*__SIZEOF_POINTER__)(sp) + sd a1, (1*__SIZEOF_POINTER__)(sp) + + csrr a0, CSR_SSTATUS + and a0, a0, (1 << SSTATUS_SPP_BIT_POSITION) + bnez a0, InTrap // We are in supervisor mode (SMode) + // trap handler. + // Skip enabling SIE becasue SIE + // is set to disabled by RISC-V hart + // when the trap takes hart to SMode. + + li a1, SSTATUS_SIE + csrs CSR_SSTATUS, a1 +InTrap: + ld a0, (0*__SIZEOF_POINTER__)(sp) + ld a1, (1*__SIZEOF_POINTER__)(sp) + add sp, sp, 2*(__SIZEOF_POINTER__) + ret + +// +// This routine returns supervisor mode interrupt +// status. +// +ASM_PFX(RiscVGetSupervisorModeInterrupts): + csrr a0, CSR_SSTATUS + andi a0, a0, SSTATUS_SIE + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVSetJumpLongJump.S b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVSetJumpLongJump.S new file mode 100644 index 000000000..34486eabb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/RiscV64/RiscVSetJumpLongJump.S @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------------ +// +// Set/Long jump for RISC-V +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ +# define REG_S sd +# define REG_L ld +# define SZREG 8 +.align 3 + .globl SetJump + +SetJump: + REG_S ra, 0*SZREG(a0) + REG_S s0, 1*SZREG(a0) + REG_S s1, 2*SZREG(a0) + REG_S s2, 3*SZREG(a0) + REG_S s3, 4*SZREG(a0) + REG_S s4, 5*SZREG(a0) + REG_S s5, 6*SZREG(a0) + REG_S s6, 7*SZREG(a0) + REG_S s7, 8*SZREG(a0) + REG_S s8, 9*SZREG(a0) + REG_S s9, 10*SZREG(a0) + REG_S s10, 11*SZREG(a0) + REG_S s11, 12*SZREG(a0) + REG_S sp, 13*SZREG(a0) + li a0, 0 + ret + + .globl InternalLongJump +InternalLongJump: + REG_L ra, 0*SZREG(a0) + REG_L s0, 1*SZREG(a0) + REG_L s1, 2*SZREG(a0) + REG_L s2, 3*SZREG(a0) + REG_L s3, 4*SZREG(a0) + REG_L s4, 5*SZREG(a0) + REG_L s5, 6*SZREG(a0) + REG_L s6, 7*SZREG(a0) + REG_L s7, 8*SZREG(a0) + REG_L s8, 9*SZREG(a0) + REG_L s9, 10*SZREG(a0) + REG_L s10, 11*SZREG(a0) + REG_L s11, 12*SZREG(a0) + REG_L sp, 13*SZREG(a0) + + add a0, s0, 0 + add a1, s1, 0 + add a2, s2, 0 + add a3, s3, 0 + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/SafeString.c b/roms/edk2/MdePkg/Library/BaseLib/SafeString.c new file mode 100644 index 000000000..3bb23ca1a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SafeString.c @@ -0,0 +1,3535 @@ +/** @file + Safe String functions. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength)) + +#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength)) + +#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \ + do { \ + if (!(Expression)) { \ + DEBUG ((DEBUG_VERBOSE, \ + "%a(%d) %a: SAFE_STRING_CONSTRAINT_CHECK(%a) failed. Return %r\n", \ + __FILE__, __LINE__, __FUNCTION__, #Expression, Status)); \ + return Status; \ + } \ + } while (FALSE) + +/** + Returns if 2 memory blocks are overlapped. + + @param Base1 Base address of 1st memory block. + @param Size1 Size of 1st memory block. + @param Base2 Base address of 2nd memory block. + @param Size2 Size of 2nd memory block. + + @retval TRUE 2 memory blocks are overlapped. + @retval FALSE 2 memory blocks are not overlapped. +**/ +BOOLEAN +InternalSafeStringIsOverlap ( + IN VOID *Base1, + IN UINTN Size1, + IN VOID *Base2, + IN UINTN Size2 + ) +{ + if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) || + (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) { + return TRUE; + } + return FALSE; +} + +/** + Returns if 2 Unicode strings are not overlapped. + + @param Str1 Start address of 1st Unicode string. + @param Size1 The number of char in 1st Unicode string, + including terminating null char. + @param Str2 Start address of 2nd Unicode string. + @param Size2 The number of char in 2nd Unicode string, + including terminating null char. + + @retval TRUE 2 Unicode strings are NOT overlapped. + @retval FALSE 2 Unicode strings are overlapped. +**/ +BOOLEAN +InternalSafeStringNoStrOverlap ( + IN CHAR16 *Str1, + IN UINTN Size1, + IN CHAR16 *Str2, + IN UINTN Size2 + ) +{ + return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16)); +} + +/** + Returns if 2 Ascii strings are not overlapped. + + @param Str1 Start address of 1st Ascii string. + @param Size1 The number of char in 1st Ascii string, + including terminating null char. + @param Str2 Start address of 2nd Ascii string. + @param Size2 The number of char in 2nd Ascii string, + including terminating null char. + + @retval TRUE 2 Ascii strings are NOT overlapped. + @retval FALSE 2 Ascii strings are overlapped. +**/ +BOOLEAN +InternalSafeStringNoAsciiStrOverlap ( + IN CHAR8 *Str1, + IN UINTN Size1, + IN CHAR8 *Str2, + IN UINTN Size2 + ) +{ + return !InternalSafeStringIsOverlap (Str1, Size1, Str2, Size2); +} + +/** + Returns the length of a Null-terminated Unicode string. + + This function is similar as strlen_s defined in C11. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including terminating null char. + + @retval 0 If String is NULL. + @retval MaxSize If there is no null character in the first MaxSize characters of String. + @return The number of characters that percede the terminating null character. + +**/ +UINTN +EFIAPI +StrnLenS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ) +{ + UINTN Length; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero. + // + if ((String == NULL) || (MaxSize == 0)) { + return 0; + } + + // + // Otherwise, the StrnLenS function returns the number of characters that precede the + // terminating null character. If there is no null character in the first MaxSize characters of + // String then StrnLenS returns MaxSize. At most the first MaxSize characters of String shall + // be accessed by StrnLenS. + // + Length = 0; + while (String[Length] != 0) { + if (Length >= MaxSize - 1) { + return MaxSize; + } + Length++; + } + return Length; +} + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Unicode string + specified by String in bytes, including the Null terminator. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR16) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Unicode string in bytes, including + the Null terminator. + +**/ +UINTN +EFIAPI +StrnSizeS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the StrnSizeS function returns zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the StrnSizeS function returns the size of the Null-terminated + // Unicode string in bytes, including the Null terminator. If there is no + // Null terminator in the first MaxSize characters of String, then StrnSizeS + // returns (sizeof (CHAR16) * (MaxSize + 1)) to keep a consistent map with + // the StrnLenS function. + // + return (StrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** + Copies the string pointed to by Source (including the terminating null char) + to the array pointed to by Destination. + + This function is similar as strcpy_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrCpyS ( + OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrCpyS function copies the string pointed to by Source (including the terminating + // null character) into the array pointed to by Destination. + // + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Copies not more than Length successive char from the string pointed to by + Source to the array pointed to by Destination. If no null char is copied from + Source, then Destination[Length] is always set to null. + + This function is similar as strncpy_s defined in C11. + + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrnCpyS ( + OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, MIN (DestMax, Length)); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrnCpyS function copies not more than Length successive characters (characters that + // follow a null character are not copied) from the array pointed to by Source to the array + // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null + // character. + // + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends a copy of the string pointed to by Source (including the terminating + null char) to the end of the string pointed to by Destination. + + This function is similar as strcat_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrCatS ( + IN OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrCatS. + // + DestLen = StrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. CopyLen shall be greater than StrnLenS(Source, CopyLen). + // + SourceLen = StrnLenS (Source, CopyLen); + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 6. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrCatS function appends a copy of the string pointed to by Source (including the + // terminating null character) to the end of the string pointed to by Destination. The initial character + // from Source overwrites the null character at the end of Destination. + // + Destination = Destination + DestLen; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends not more than Length successive char from the string pointed to by + Source to the end of the string pointed to by Destination. If no null char is + copied from Source, then Destination[StrLen(Destination) + Length] is always + set to null. + + This function is similar as strncat_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrnCatS ( + IN OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrnCatS. + // + DestLen = StrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. If Length is not less than CopyLen, then CopyLen shall be greater than StrnLenS(Source, CopyLen). + // + SourceLen = StrnLenS (Source, MIN (CopyLen, Length)); + if (Length >= CopyLen) { + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 6. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrnCatS function appends not more than Length successive characters (characters + // that follow a null character are not copied) from the array pointed to by Source to the end of + // the string pointed to by Destination. The initial character from Source overwrites the null character at + // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to + // a null character. + // + Destination = Destination + DestLen; + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (CharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (CharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to IPv6 address and prefix length. + + This function outputs a value of type IPv6_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the Unicode string specified + by String. The format of the input Unicode string String is as follows: + + X:X:X:X:X:X:X:X[/P] + + X contains one to four hexadecimal digit characters in the range [0-9], [a-f] and + [A-F]. X is converted to a value of type UINT16, whose low byte is stored in low + memory address and high byte is stored in high memory address. P contains decimal + digit characters in the range [0-9]. The running zero in the beginning of P will + be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid hexadecimal digit character after eight X's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + "::" can be used to compress one or more groups of X when X contains only 0. + The "::" can only appear once in the String. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv6 address. + @param PrefixLength Pointer to the converted IPv6 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If X contains more than four hexadecimal + digit characters. + If String contains "::" and number of X + is not less than 8. + If P starts with character that is not a + valid decimal digit character. + If the decimal number converted from P + exceeds 128. + +**/ +RETURN_STATUS +EFIAPI +StrToIpv6Address ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT IPv6_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv6_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CONST CHAR16 *Pointer; + CHAR16 *End; + UINTN CompressStart; + BOOLEAN ExpectPrefix; + + LocalPrefixLength = MAX_UINT8; + CompressStart = ARRAY_SIZE (Address->Addr); + ExpectPrefix = FALSE; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer != L':') { + // + // ":" or "/" should be followed by digit characters. + // + return RETURN_UNSUPPORTED; + } + + // + // Meet second ":" after previous ":" or "/" + // or meet first ":" in the beginning of String. + // + if (ExpectPrefix) { + // + // ":" shall not be after "/" + // + return RETURN_UNSUPPORTED; + } + + if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // "::" can only appear once. + // "::" can only appear when address is not full length. + // + return RETURN_UNSUPPORTED; + } else { + // + // Remember the start of zero compressing. + // + CompressStart = AddressIndex; + Pointer++; + + if (CompressStart == 0) { + if (*Pointer != L':') { + // + // Single ":" shall not be in the beginning of String. + // + return RETURN_UNSUPPORTED; + } + Pointer++; + } + } + } + + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer == L'/') { + // + // Might be optional "/P" after "::". + // + if (CompressStart != AddressIndex) { + return RETURN_UNSUPPORTED; + } + } else { + break; + } + } else { + if (!ExpectPrefix) { + // + // Get X. + // + Status = StrHexToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End - Pointer > 4) { + // + // Number of hexadecimal digit characters is no more than 4. + // + return RETURN_UNSUPPORTED; + } + Pointer = End; + // + // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4. + // + ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr)); + LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8); + LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn; + AddressIndex += 2; + } else { + // + // Get P, then exit the loop. + // + Status = StrDecimalToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) { + // + // Prefix length should not exceed 128. + // + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + Pointer = End; + break; + } + } + + // + // Skip ':' or "/" + // + if (*Pointer == L'/') { + ExpectPrefix = TRUE; + } else if (*Pointer == L':') { + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // Meet additional ":" after all 8 16-bit address + // + break; + } + } else { + // + // Meet other character that is not "/" or ":" after all 8 16-bit address + // + break; + } + Pointer++; + } + + if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) || + (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr)) + ) { + // + // Full length of address shall not have compressing zeros. + // Non-full length of address shall have compressing zeros. + // + return RETURN_UNSUPPORTED; + } + CopyMem (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart); + ZeroMem (&Address->Addr[CompressStart], ARRAY_SIZE (Address->Addr) - AddressIndex); + if (AddressIndex > CompressStart) { + CopyMem ( + &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex], + &LocalAddress.Addr[CompressStart], + AddressIndex - CompressStart + ); + } + + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to IPv4 address and prefix length. + + This function outputs a value of type IPv4_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the Unicode string specified + by String. The format of the input Unicode string String is as follows: + + D.D.D.D[/P] + + D and P are decimal digit characters in the range [0-9]. The running zero in + the beginning of D and P will be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid decimal digit character after four D's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv4 address. + @param PrefixLength Pointer to the converted IPv4 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not in the correct format. + If any decimal number converted from D + exceeds 255. + If the decimal number converted from P + exceeds 32. + +**/ +RETURN_STATUS +EFIAPI +StrToIpv4Address ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT IPv4_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv4_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CHAR16 *Pointer; + + LocalPrefixLength = MAX_UINT8; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsDecimalDigitCharacter (*Pointer)) { + // + // D or P contains invalid characters. + // + break; + } + + // + // Get D or P. + // + Status = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer, &Uintn); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // It's P. + // + if (Uintn > 32) { + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + } else { + // + // It's D. + // + if (Uintn > MAX_UINT8) { + return RETURN_UNSUPPORTED; + } + LocalAddress.Addr[AddressIndex] = (UINT8) Uintn; + AddressIndex++; + } + + // + // Check the '.' or '/', depending on the AddressIndex. + // + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'/') { + // + // '/P' is in the String. + // Skip "/" and get P in next loop. + // + Pointer++; + } else { + // + // '/P' is not in the String. + // + break; + } + } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'.') { + // + // D should be followed by '.' + // + Pointer++; + } else { + return RETURN_UNSUPPORTED; + } + } + } + + if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + return RETURN_UNSUPPORTED; + } + + CopyMem (Address, &LocalAddress, sizeof (*Address)); + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode GUID string to a value of type + EFI_GUID. + + This function outputs a GUID value by interpreting the contents of + the Unicode string specified by String. The format of the input + Unicode string String consists of 36 characters, as follows: + + aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + + The pairs aa - pp are two characters in the range [0-9], [a-f] and + [A-F], with each pair representing a single byte hexadecimal value. + + The mapping between String and the EFI_GUID structure is as follows: + aa Data1[24:31] + bb Data1[16:23] + cc Data1[8:15] + dd Data1[0:7] + ee Data2[8:15] + ff Data2[0:7] + gg Data3[8:15] + hh Data3[0:7] + ii Data4[0:7] + jj Data4[8:15] + kk Data4[16:23] + ll Data4[24:31] + mm Data4[32:39] + nn Data4[40:47] + oo Data4[48:55] + pp Data4[56:63] + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Guid Pointer to the converted GUID. + + @retval RETURN_SUCCESS Guid is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not as the above format. + +**/ +RETURN_STATUS +EFIAPI +StrToGuid ( + IN CONST CHAR16 *String, + OUT GUID *Guid + ) +{ + RETURN_STATUS Status; + GUID LocalGuid; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER); + + // + // Get aabbccdd in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1); + String += 2 * sizeof (LocalGuid.Data1) + 1; + + // + // Get eeff in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2); + String += 2 * sizeof (LocalGuid.Data2) + 1; + + // + // Get gghh in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3); + String += 2 * sizeof (LocalGuid.Data3) + 1; + + // + // Get iijj. + // + Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2); + if (RETURN_ERROR (Status) || String[2 * 2] != L'-') { + return RETURN_UNSUPPORTED; + } + String += 2 * 2 + 1; + + // + // Get kkllmmnnoopp. + // + Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + CopyGuid (Guid, &LocalGuid); + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a byte array. + + This function outputs a byte array by interpreting the contents of + the Unicode string specified by String in hexadecimal format. The format of + the input Unicode string String is: + + [XX]* + + X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F]. + The function decodes every two hexadecimal digit characters as one byte. The + decoding stops after Length of characters and outputs Buffer containing + (Length / 2) bytes. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Length The number of Unicode characters to decode. + @param Buffer Pointer to the converted bytes array. + @param MaxBufferSize The maximum size of Buffer. + + @retval RETURN_SUCCESS Buffer is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If Length is not multiple of 2. + If PcdMaximumUnicodeStringLength is not zero, + and Length is greater than + PcdMaximumUnicodeStringLength. + @retval RETURN_UNSUPPORTED If Length of characters from String contain + a character that is not valid hexadecimal + digit characters, or a Null-terminator. + @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2). +**/ +RETURN_STATUS +EFIAPI +StrHexToBytes ( + IN CONST CHAR16 *String, + IN UINTN Length, + OUT UINT8 *Buffer, + IN UINTN MaxBufferSize + ) +{ + UINTN Index; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Buffer shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Length shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. Length shall not be odd. + // + SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER); + + // + // 4. MaxBufferSize shall equal to or greater than Length / 2. + // + SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL); + + // + // 5. String shall not contains invalid hexadecimal digits. + // + for (Index = 0; Index < Length; Index++) { + if (!InternalIsHexaDecimalDigitCharacter (String[Index])) { + break; + } + } + if (Index != Length) { + return RETURN_UNSUPPORTED; + } + + // + // Convert the hex string to bytes. + // + for(Index = 0; Index < Length; Index++) { + + // + // For even characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & BIT0) == 0) { + Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4; + } else { + Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]); + } + } + return RETURN_SUCCESS; +} + +/** + Returns the length of a Null-terminated Ascii string. + + This function is similar as strlen_s defined in C11. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including terminating null char. + + @retval 0 If String is NULL. + @retval MaxSize If there is no null character in the first MaxSize characters of String. + @return The number of characters that percede the terminating null character. + +**/ +UINTN +EFIAPI +AsciiStrnLenS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ) +{ + UINTN Length; + + // + // If String is a null pointer or MaxSize is 0, then the AsciiStrnLenS function returns zero. + // + if ((String == NULL) || (MaxSize == 0)) { + return 0; + } + + // + // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the + // terminating null character. If there is no null character in the first MaxSize characters of + // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall + // be accessed by AsciiStrnLenS. + // + Length = 0; + while (String[Length] != 0) { + if (Length >= MaxSize - 1) { + return MaxSize; + } + Length++; + } + return Length; +} + +/** + Returns the size of a Null-terminated Ascii string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Ascii string specified + by String in bytes, including the Null terminator. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR8) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Ascii string in bytes, including the + Null terminator. + +**/ +UINTN +EFIAPI +AsciiStrnSizeS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the AsciiStrnSizeS function returns + // zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the AsciiStrnSizeS function returns the size of the + // Null-terminated Ascii string in bytes, including the Null terminator. If + // there is no Null terminator in the first MaxSize characters of String, + // then AsciiStrnSizeS returns (sizeof (CHAR8) * (MaxSize + 1)) to keep a + // consistent map with the AsciiStrnLenS function. + // + return (AsciiStrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** + Copies the string pointed to by Source (including the terminating null char) + to the array pointed to by Destination. + + This function is similar as strcpy_s defined in C11. + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrCpyS ( + OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source + ) +{ + UINTN SourceLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating + // null character) into the array pointed to by Destination. + // + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Copies not more than Length successive char from the string pointed to by + Source to the array pointed to by Destination. If no null char is copied from + Source, then Destination[Length] is always set to null. + + This function is similar as strncpy_s defined in C11. + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to copy. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrnCpyS ( + OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + UINTN SourceLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, MIN (DestMax, Length)); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrnCpyS function copies not more than Length successive characters (characters that + // follow a null character are not copied) from the array pointed to by Source to the array + // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null + // character. + // + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends a copy of the string pointed to by Source (including the terminating + null char) to the end of the string pointed to by Destination. + + This function is similar as strcat_s defined in C11. + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrCatS ( + IN OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + // + // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS. + // + DestLen = AsciiStrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen). + // + SourceLen = AsciiStrnLenS (Source, CopyLen); + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 6. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the + // terminating null character) to the end of the string pointed to by Destination. The initial character + // from Source overwrites the null character at the end of Destination. + // + Destination = Destination + DestLen; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends not more than Length successive char from the string pointed to by + Source to the end of the string pointed to by Destination. If no null char is + copied from Source, then Destination[StrLen(Destination) + Length] is always + set to null. + + This function is similar as strncat_s defined in C11. + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to copy. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrnCatS ( + IN OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + // + // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS. + // + DestLen = AsciiStrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen). + // + SourceLen = AsciiStrnLenS (Source, MIN (CopyLen, Length)); + if (Length >= CopyLen) { + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 6. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrnCatS function appends not more than Length successive characters (characters + // that follow a null character are not copied) from the array pointed to by Source to the end of + // the string pointed to by Destination. The initial character from Source overwrites the null character at + // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to + // a null character. + // + Destination = Destination + DestLen; + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - '0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (AsciiCharToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalAsciiHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (AsciiCharToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to a Null-terminated + ASCII string. + + This function is similar to AsciiStrCpyS. + + This function converts the content of the Unicode string Source + to the ASCII string Destination by copying the lower 8 bits of + each Unicode character. The function terminates the ASCII string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in + the upper 8 bits, then ASSERT(). + + If Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Destination The pointer to a Null-terminated ASCII string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrToAsciiStrS ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination, + IN UINTN DestMax + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS (Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + // + // convert string + // + while (*Source != '\0') { + // + // If any Unicode characters in Source contain + // non-zero value in the upper 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + } + *Destination = '\0'; + + return RETURN_SUCCESS; +} + +/** + Convert not more than Length successive characters from a Null-terminated + Unicode string to a Null-terminated Ascii string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Unicode string Source to the Ascii string Destination by copying the lower 8 + bits of each Unicode character. The function terminates the Ascii string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8)) + in bytes. + + If any Unicode characters in Source contain non-zero value in the upper 8 + bits, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to + convert. + @param Destination The pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii char, + including terminating null char. + @param DestinationLength The number of Unicode characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrnToAsciiStrS ( + IN CONST CHAR16 *Source, + IN UINTN Length, + OUT CHAR8 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + // + // If any Unicode characters in Source contain non-zero value in the upper + // 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert one Null-terminated ASCII string to a Null-terminated + Unicode string. + + This function is similar to StrCpyS. + + This function converts the contents of the ASCII string Source to the Unicode + string Destination. The function terminates the Unicode string Destination by + appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Source The pointer to a Null-terminated ASCII string. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToUnicodeStrS ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination, + IN UINTN DestMax + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX or ASCII_RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // Convert string + // + while (*Source != '\0') { + *(Destination++) = (CHAR16)(UINT8)*(Source++); + } + *Destination = '\0'; + + return RETURN_SUCCESS; +} + +/** + Convert not more than Length successive characters from a Null-terminated + Ascii string to a Null-terminated Unicode string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Ascii string Source to the Unicode string Destination. The function + terminates the Unicode string Destination by appending a Null-terminator + character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to convert. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode char, + including terminating null char. + @param DestinationLength The number of Ascii characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(AsciiStrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrnToUnicodeStrS ( + IN CONST CHAR8 *Source, + IN UINTN Length, + OUT CHAR16 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + *(Destination++) = (CHAR16)(UINT8)*(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII string to IPv6 address and prefix length. + + This function outputs a value of type IPv6_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the ASCII string specified + by String. The format of the input ASCII string String is as follows: + + X:X:X:X:X:X:X:X[/P] + + X contains one to four hexadecimal digit characters in the range [0-9], [a-f] and + [A-F]. X is converted to a value of type UINT16, whose low byte is stored in low + memory address and high byte is stored in high memory address. P contains decimal + digit characters in the range [0-9]. The running zero in the beginning of P will + be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid hexadecimal digit character after eight X's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + "::" can be used to compress one or more groups of X when X contains only 0. + The "::" can only appear once in the String. + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated ASCII string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv6 address. + @param PrefixLength Pointer to the converted IPv6 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If X contains more than four hexadecimal + digit characters. + If String contains "::" and number of X + is not less than 8. + If P starts with character that is not a + valid decimal digit character. + If the decimal number converted from P + exceeds 128. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToIpv6Address ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT IPv6_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv6_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CONST CHAR8 *Pointer; + CHAR8 *End; + UINTN CompressStart; + BOOLEAN ExpectPrefix; + + LocalPrefixLength = MAX_UINT8; + CompressStart = ARRAY_SIZE (Address->Addr); + ExpectPrefix = FALSE; + + // + // None of String or Address shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalAsciiIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer != ':') { + // + // ":" or "/" should be followed by digit characters. + // + return RETURN_UNSUPPORTED; + } + + // + // Meet second ":" after previous ":" or "/" + // or meet first ":" in the beginning of String. + // + if (ExpectPrefix) { + // + // ":" shall not be after "/" + // + return RETURN_UNSUPPORTED; + } + + if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // "::" can only appear once. + // "::" can only appear when address is not full length. + // + return RETURN_UNSUPPORTED; + } else { + // + // Remember the start of zero compressing. + // + CompressStart = AddressIndex; + Pointer++; + + if (CompressStart == 0) { + if (*Pointer != ':') { + // + // Single ":" shall not be in the beginning of String. + // + return RETURN_UNSUPPORTED; + } + Pointer++; + } + } + } + + if (!InternalAsciiIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer == '/') { + // + // Might be optional "/P" after "::". + // + if (CompressStart != AddressIndex) { + return RETURN_UNSUPPORTED; + } + } else { + break; + } + } else { + if (!ExpectPrefix) { + // + // Get X. + // + Status = AsciiStrHexToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End - Pointer > 4) { + // + // Number of hexadecimal digit characters is no more than 4. + // + return RETURN_UNSUPPORTED; + } + Pointer = End; + // + // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4. + // + ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr)); + LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8); + LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn; + AddressIndex += 2; + } else { + // + // Get P, then exit the loop. + // + Status = AsciiStrDecimalToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) { + // + // Prefix length should not exceed 128. + // + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + Pointer = End; + break; + } + } + + // + // Skip ':' or "/" + // + if (*Pointer == '/') { + ExpectPrefix = TRUE; + } else if (*Pointer == ':') { + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // Meet additional ":" after all 8 16-bit address + // + break; + } + } else { + // + // Meet other character that is not "/" or ":" after all 8 16-bit address + // + break; + } + Pointer++; + } + + if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) || + (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr)) + ) { + // + // Full length of address shall not have compressing zeros. + // Non-full length of address shall have compressing zeros. + // + return RETURN_UNSUPPORTED; + } + CopyMem (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart); + ZeroMem (&Address->Addr[CompressStart], ARRAY_SIZE (Address->Addr) - AddressIndex); + if (AddressIndex > CompressStart) { + CopyMem ( + &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex], + &LocalAddress.Addr[CompressStart], + AddressIndex - CompressStart + ); + + } + + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII string to IPv4 address and prefix length. + + This function outputs a value of type IPv4_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the ASCII string specified + by String. The format of the input ASCII string String is as follows: + + D.D.D.D[/P] + + D and P are decimal digit characters in the range [0-9]. The running zero in + the beginning of D and P will be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid decimal digit character after four D's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated ASCII string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv4 address. + @param PrefixLength Pointer to the converted IPv4 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not in the correct format. + If any decimal number converted from D + exceeds 255. + If the decimal number converted from P + exceeds 32. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToIpv4Address ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT IPv4_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv4_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CHAR8 *Pointer; + + LocalPrefixLength = MAX_UINT8; + + // + // None of String or Address shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = (CHAR8 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalAsciiIsDecimalDigitCharacter (*Pointer)) { + // + // D or P contains invalid characters. + // + break; + } + + // + // Get D or P. + // + Status = AsciiStrDecimalToUintnS ((CONST CHAR8 *) Pointer, &Pointer, &Uintn); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // It's P. + // + if (Uintn > 32) { + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + } else { + // + // It's D. + // + if (Uintn > MAX_UINT8) { + return RETURN_UNSUPPORTED; + } + LocalAddress.Addr[AddressIndex] = (UINT8) Uintn; + AddressIndex++; + } + + // + // Check the '.' or '/', depending on the AddressIndex. + // + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + if (*Pointer == '/') { + // + // '/P' is in the String. + // Skip "/" and get P in next loop. + // + Pointer++; + } else { + // + // '/P' is not in the String. + // + break; + } + } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + if (*Pointer == '.') { + // + // D should be followed by '.' + // + Pointer++; + } else { + return RETURN_UNSUPPORTED; + } + } + } + + if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + return RETURN_UNSUPPORTED; + } + + CopyMem (Address, &LocalAddress, sizeof (*Address)); + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII GUID string to a value of type + EFI_GUID. + + This function outputs a GUID value by interpreting the contents of + the ASCII string specified by String. The format of the input + ASCII string String consists of 36 characters, as follows: + + aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + + The pairs aa - pp are two characters in the range [0-9], [a-f] and + [A-F], with each pair representing a single byte hexadecimal value. + + The mapping between String and the EFI_GUID structure is as follows: + aa Data1[24:31] + bb Data1[16:23] + cc Data1[8:15] + dd Data1[0:7] + ee Data2[8:15] + ff Data2[0:7] + gg Data3[8:15] + hh Data3[0:7] + ii Data4[0:7] + jj Data4[8:15] + kk Data4[16:23] + ll Data4[24:31] + mm Data4[32:39] + nn Data4[40:47] + oo Data4[48:55] + pp Data4[56:63] + + @param String Pointer to a Null-terminated ASCII string. + @param Guid Pointer to the converted GUID. + + @retval RETURN_SUCCESS Guid is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not as the above format. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToGuid ( + IN CONST CHAR8 *String, + OUT GUID *Guid + ) +{ + RETURN_STATUS Status; + GUID LocalGuid; + + // + // None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER); + + // + // Get aabbccdd in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1); + String += 2 * sizeof (LocalGuid.Data1) + 1; + + // + // Get eeff in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2); + String += 2 * sizeof (LocalGuid.Data2) + 1; + + // + // Get gghh in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3); + String += 2 * sizeof (LocalGuid.Data3) + 1; + + // + // Get iijj. + // + Status = AsciiStrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2); + if (RETURN_ERROR (Status) || String[2 * 2] != '-') { + return RETURN_UNSUPPORTED; + } + String += 2 * 2 + 1; + + // + // Get kkllmmnnoopp. + // + Status = AsciiStrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + CopyGuid (Guid, &LocalGuid); + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII hexadecimal string to a byte array. + + This function outputs a byte array by interpreting the contents of + the ASCII string specified by String in hexadecimal format. The format of + the input ASCII string String is: + + [XX]* + + X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F]. + The function decodes every two hexadecimal digit characters as one byte. The + decoding stops after Length of characters and outputs Buffer containing + (Length / 2) bytes. + + @param String Pointer to a Null-terminated ASCII string. + @param Length The number of ASCII characters to decode. + @param Buffer Pointer to the converted bytes array. + @param MaxBufferSize The maximum size of Buffer. + + @retval RETURN_SUCCESS Buffer is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If Length is not multiple of 2. + If PcdMaximumAsciiStringLength is not zero, + and Length is greater than + PcdMaximumAsciiStringLength. + @retval RETURN_UNSUPPORTED If Length of characters from String contain + a character that is not valid hexadecimal + digit characters, or a Null-terminator. + @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2). +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToBytes ( + IN CONST CHAR8 *String, + IN UINTN Length, + OUT UINT8 *Buffer, + IN UINTN MaxBufferSize + ) +{ + UINTN Index; + + // + // 1. None of String or Buffer shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Length shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. Length shall not be odd. + // + SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER); + + // + // 4. MaxBufferSize shall equal to or greater than Length / 2. + // + SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL); + + // + // 5. String shall not contains invalid hexadecimal digits. + // + for (Index = 0; Index < Length; Index++) { + if (!InternalAsciiIsHexaDecimalDigitCharacter (String[Index])) { + break; + } + } + if (Index != Length) { + return RETURN_UNSUPPORTED; + } + + // + // Convert the hex string to bytes. + // + for(Index = 0; Index < Length; Index++) { + + // + // For even characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & BIT0) == 0) { + Buffer[Index / 2] = (UINT8) InternalAsciiHexCharToUintn (String[Index]) << 4; + } else { + Buffer[Index / 2] |= (UINT8) InternalAsciiHexCharToUintn (String[Index]); + } + } + return RETURN_SUCCESS; +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/SetJump.c b/roms/edk2/MdePkg/Library/BaseLib/SetJump.c new file mode 100644 index 000000000..516f92f28 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SetJump.c @@ -0,0 +1,34 @@ +/** @file + Internal ASSERT () functions for SetJump. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Worker function that checks ASSERT condition for JumpBuffer + + Checks ASSERT condition for JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For IPF CPUs, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + +**/ +VOID +EFIAPI +InternalAssertJumpBuffer ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ) +{ + ASSERT (JumpBuffer != NULL); + + ASSERT (((UINTN)JumpBuffer & (BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT - 1)) == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/String.c b/roms/edk2/MdePkg/Library/BaseLib/String.c new file mode 100644 index 000000000..45198373f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/String.c @@ -0,0 +1,2270 @@ +/** @file + Unicode and ASCII string primitives. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function will be deprecated for security reason. + + Copies one Null-terminated Unicode string to another Null-terminated Unicode + string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param Destination A pointer to a Null-terminated Unicode string. + @param Source A pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ) +{ + CHAR16 *ReturnValue; + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > StrLen (Source)); + ASSERT ((UINTN)(Source - Destination) > StrLen (Source)); + + ReturnValue = Destination; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + return ReturnValue; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Copies up to a specified length from one Null-terminated Unicode string to + another Null-terminated Unicode string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. At most, Length Unicode + characters are copied from Source to Destination. If Length is 0, then + Destination is returned unmodified. If Length is greater that the number of + Unicode characters in Source, then Destination is padded with Null Unicode + characters. If Source and Destination overlap, then the results are + undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param Destination A pointer to a Null-terminated Unicode string. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + CHAR16 *ReturnValue; + + if (Length == 0) { + return Destination; + } + + // + // Destination cannot be NULL if Length is not zero + // + ASSERT (Destination != NULL); + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > StrLen (Source)); + ASSERT ((UINTN)(Source - Destination) >= Length); + + if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) { + ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength)); + } + + ReturnValue = Destination; + + while ((*Source != L'\0') && (Length > 0)) { + *(Destination++) = *(Source++); + Length--; + } + + ZeroMem (Destination, Length * sizeof (*Destination)); + return ReturnValue; +} +#endif + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + ASSERT (((UINTN) String & BIT0) == 0); + + for (Length = 0; *String != L'\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) { + ASSERT (Length < PcdGet32 (PcdMaximumUnicodeStringLength)); + } + } + return Length; +} + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of 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(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ) +{ + return (StrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated Unicode string. + @param SecondString A pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + return *FirstString - *SecondString; +} + +/** + Compares up to a specified length the contents of two Null-terminated Unicode strings, + and returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString A pointer to a Null-terminated Unicode string. + @param SecondString A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) { + ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength)); + } + + while ((*FirstString != L'\0') && + (*SecondString != L'\0') && + (*FirstString == *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return *FirstString - *SecondString; +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function will be deprecated for security reason. + + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string, and returns the concatenated Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination. The Null-terminated concatenated + Unicode String is returned. If Source and Destination overlap, then the + results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param Destination A pointer to a Null-terminated Unicode string. + @param Source A pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ) +{ + StrCpy (Destination + StrLen (Destination), Source); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (StrSize (Destination) != 0); + return Destination; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Concatenates up to a specified length one Null-terminated Unicode to the end + of another Null-terminated Unicode string, and returns the concatenated + Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination, and Destination is returned. At + most, Length Unicode characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than PcdMaximumUnicodeStringLength + Unicode characters, not including the Null-terminator, then ASSERT(). + + @param Destination A pointer to a Null-terminated Unicode string. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to concatenate from + Source. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + UINTN DestinationLen; + + DestinationLen = StrLen (Destination); + StrnCpy (Destination + DestinationLen, Source, Length); + Destination[DestinationLen + Length] = L'\0'; + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (StrSize (Destination) != 0); + return Destination; +} +#endif + +/** + Returns the first occurrence of a Null-terminated Unicode sub-string + in a Null-terminated Unicode string. + + This function scans the contents of the Null-terminated Unicode string + specified by String and returns the first occurrence of SearchString. + If SearchString is not found in String, then NULL is returned. If + the length of SearchString is zero, then String is + returned. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If SearchString is NULL, then ASSERT(). + If SearchString is not aligned on a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and SearchString + or String contains more than PcdMaximumUnicodeStringLength Unicode + characters, not including the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param SearchString A pointer to a Null-terminated Unicode string to search for. + + @retval NULL If the SearchString does not appear in String. + @return others If there is a match. + +**/ +CHAR16 * +EFIAPI +StrStr ( + IN CONST CHAR16 *String, + IN CONST CHAR16 *SearchString + ) +{ + CONST CHAR16 *FirstMatch; + CONST CHAR16 *SearchStringTmp; + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (String) != 0); + ASSERT (StrSize (SearchString) != 0); + + if (*SearchString == L'\0') { + return (CHAR16 *) String; + } + + while (*String != L'\0') { + SearchStringTmp = SearchString; + FirstMatch = String; + + while ((*String == *SearchStringTmp) + && (*String != L'\0')) { + String++; + SearchStringTmp++; + } + + if (*SearchStringTmp == L'\0') { + return (CHAR16 *) FirstMatch; + } + + if (*String == L'\0') { + return NULL; + } + + String = FirstMatch + 1; + } + + return NULL; +} + +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + L'0' to L'9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + return (BOOLEAN) (Char >= L'0' && Char <= L'9'); +} + +/** + Convert a Unicode character to upper case only if + it maps to a valid small-case ASCII character. + + This internal function only deal with Unicode character + which maps to a valid small-case ASCII character, i.e. + L'a' to L'z'. For other Unicode character, the input character + is returned directly. + + @param Char The character to convert. + + @retval LowerCharacter If the Char is with range L'a' to L'z'. + @retval Unchanged Otherwise. + +**/ +CHAR16 +EFIAPI +CharToUpper ( + IN CHAR16 Char + ) +{ + if (Char >= L'a' && Char <= L'z') { + return (CHAR16) (Char - (L'a' - L'A')); + } + + return Char; +} + +/** + Convert a Unicode character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other + Unicode character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalHexCharToUintn ( + IN CHAR16 Char + ) +{ + if (InternalIsDecimalDigitCharacter (Char)) { + return Char - L'0'; + } + + return (10 + CharToUpper (Char) - L'A'); +} + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + + return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) || + (Char >= L'A' && Char <= L'F') || + (Char >= L'a' && Char <= L'f')); +} + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINTN, then MAX_UINTN is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters, not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrDecimalToUintn ( + IN CONST CHAR16 *String + ) +{ + UINTN Result; + + StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINT64, then MAX_UINT64 is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters, not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrDecimalToUint64 ( + IN CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINTN, then MAX_UINTN is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrHexToUintn ( + IN CONST CHAR16 *String + ) +{ + UINTN Result; + + StrHexToUintnS (String, (CHAR16 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINT64, then MAX_UINT64 is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrHexToUint64 ( + IN CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrHexToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + +/** + Check if a ASCII character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + '0' to '9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsDecimalDigitCharacter ( + IN CHAR8 Char + ) +{ + return (BOOLEAN) (Char >= '0' && Char <= '9'); +} + +/** + Check if a ASCII character is a hexadecimal character. + + This internal function checks if a ASCII character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsHexaDecimalDigitCharacter ( + IN CHAR8 Char + ) +{ + + return (BOOLEAN) (InternalAsciiIsDecimalDigitCharacter (Char) || + (Char >= 'A' && Char <= 'F') || + (Char >= 'a' && Char <= 'f')); +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is deprecated for security reason. + + Convert a Null-terminated Unicode string to a Null-terminated + ASCII string and returns the ASCII string. + + This function converts the content of the Unicode string Source + to the ASCII string Destination by copying the lower 8 bits of + each Unicode character. It returns Destination. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in + the upper 8 bits, then ASSERT(). + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and Source contains + more than PcdMaximumUnicodeStringLength Unicode characters, not including + the Null-terminator, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and Source contains more + than PcdMaximumAsciiStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param Source A pointer to a Null-terminated Unicode string. + @param Destination A pointer to a Null-terminated ASCII string. + + @return Destination. + +**/ +CHAR8 * +EFIAPI +UnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ) +{ + CHAR8 *ReturnValue; + + ASSERT (Destination != NULL); + + // + // ASSERT if Source is long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (Source) != 0); + + // + // Source and Destination should not overlap + // + ASSERT ((UINTN) (Destination - (CHAR8 *) Source) >= StrSize (Source)); + ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source)); + + + ReturnValue = Destination; + while (*Source != '\0') { + // + // If any Unicode characters in Source contain + // non-zero value in the upper 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + } + + *Destination = '\0'; + + // + // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength. + // Length tests are performed inside AsciiStrLen(). + // + ASSERT (AsciiStrSize (ReturnValue) != 0); + + return ReturnValue; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Copies one Null-terminated ASCII string to another Null-terminated ASCII + string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param Destination A pointer to a Null-terminated ASCII string. + @param Source A pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ) +{ + CHAR8 *ReturnValue; + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source)); + ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source)); + + ReturnValue = Destination; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + return ReturnValue; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Copies up to a specified length one Null-terminated ASCII string to another + Null-terminated ASCII string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. At most, Length ASCII characters + are copied from Source to Destination. If Length is 0, then Destination is + returned unmodified. If Length is greater that the number of ASCII characters + in Source, then Destination is padded with Null ASCII characters. If Source + and Destination overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param Destination A pointer to a Null-terminated ASCII string. + @param Source A pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to copy. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + CHAR8 *ReturnValue; + + if (Length == 0) { + return Destination; + } + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source)); + ASSERT ((UINTN)(Source - Destination) >= Length); + + if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) { + ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength)); + } + + ReturnValue = Destination; + + while (*Source != 0 && Length > 0) { + *(Destination++) = *(Source++); + Length--; + } + + ZeroMem (Destination, Length * sizeof (*Destination)); + return ReturnValue; +} +#endif + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + + for (Length = 0; *String != '\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) { + ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength)); + } + } + return Length; +} + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ) +{ + return (AsciiStrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + + return *FirstString - *SecondString; +} + +/** + Converts a lowercase Ascii character to upper one. + + If Chr is lowercase Ascii character, then converts it to upper one. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Chr one Ascii character + + @return The uppercase value of Ascii character + +**/ +CHAR8 +EFIAPI +AsciiCharToUpper ( + IN CHAR8 Chr + ) +{ + return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr); +} + +/** + Convert a ASCII character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + '0' to '9', 'a' to 'f' or 'A' to 'F'. For other + ASCII character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalAsciiHexCharToUintn ( + IN CHAR8 Char + ) +{ + if (InternalIsDecimalDigitCharacter (Char)) { + return Char - '0'; + } + + return (10 + AsciiCharToUpper (Char) - 'A'); +} + + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + CHAR8 UpperFirstString; + CHAR8 UpperSecondString; + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + UpperFirstString = AsciiCharToUpper (*FirstString); + UpperSecondString = AsciiCharToUpper (*SecondString); + while ((*FirstString != '\0') && (*SecondString != '\0') && (UpperFirstString == UpperSecondString)) { + FirstString++; + SecondString++; + UpperFirstString = AsciiCharToUpper (*FirstString); + UpperSecondString = AsciiCharToUpper (*SecondString); + } + + return UpperFirstString - UpperSecondString; +} + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters for compare. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) { + ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength)); + } + + while ((*FirstString != '\0') && + (*SecondString != '\0') && + (*FirstString == *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + return *FirstString - *SecondString; +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function will be deprecated for security reason. + + Concatenates one Null-terminated ASCII string to another Null-terminated + ASCII string, and returns the concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents of + Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination. The Null-terminated concatenated ASCII + String is returned. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination A pointer to a Null-terminated ASCII string. + @param Source A pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ) +{ + AsciiStrCpy (Destination + AsciiStrLen (Destination), Source); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (AsciiStrSize (Destination) != 0); + return Destination; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Concatenates up to a specified length one Null-terminated ASCII string to + the end of another Null-terminated ASCII string, and returns the + concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents + of Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination, and Destination is returned. At most, + Length ASCII characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, not including the Null-terminator, then ASSERT(). + + @param Destination A pointer to a Null-terminated ASCII string. + @param Source A pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to concatenate from + Source. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + UINTN DestinationLen; + + DestinationLen = AsciiStrLen (Destination); + AsciiStrnCpy (Destination + DestinationLen, Source, Length); + Destination[DestinationLen + Length] = '\0'; + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (AsciiStrSize (Destination) != 0); + return Destination; +} +#endif + +/** + Returns the first occurrence of a Null-terminated ASCII sub-string + in a Null-terminated ASCII string. + + This function scans the contents of the ASCII string specified by String + and returns the first occurrence of SearchString. If SearchString is not + found in String, then NULL is returned. If the length of SearchString is zero, + then String is returned. + + If String is NULL, then ASSERT(). + If SearchString is NULL, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and SearchString or + String contains more than PcdMaximumAsciiStringLength Unicode characters + not including the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + @param SearchString A pointer to a Null-terminated ASCII string to search for. + + @retval NULL If the SearchString does not appear in String. + @retval others If there is a match return the first occurrence of SearchingString. + If the length of SearchString is zero,return String. + +**/ +CHAR8 * +EFIAPI +AsciiStrStr ( + IN CONST CHAR8 *String, + IN CONST CHAR8 *SearchString + ) +{ + CONST CHAR8 *FirstMatch; + CONST CHAR8 *SearchStringTmp; + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (String) != 0); + ASSERT (AsciiStrSize (SearchString) != 0); + + if (*SearchString == '\0') { + return (CHAR8 *) String; + } + + while (*String != '\0') { + SearchStringTmp = SearchString; + FirstMatch = String; + + while ((*String == *SearchStringTmp) + && (*String != '\0')) { + String++; + SearchStringTmp++; + } + + if (*SearchStringTmp == '\0') { + return (CHAR8 *) FirstMatch; + } + + if (*String == '\0') { + return NULL; + } + + String = FirstMatch + 1; + } + + return NULL; +} + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINTN, then MAX_UINTN is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrDecimalToUintn ( + IN CONST CHAR8 *String + ) +{ + UINTN Result; + + AsciiStrDecimalToUintnS (String, (CHAR8 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINT64, then MAX_UINT64 is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrDecimalToUint64 ( + IN CONST CHAR8 *String + ) +{ + UINT64 Result; + + AsciiStrDecimalToUint64S (String, (CHAR8 **) NULL, &Result); + return Result; +} + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINTN, + then MAX_UINTN is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrHexToUintn ( + IN CONST CHAR8 *String + ) +{ + UINTN Result; + + AsciiStrHexToUintnS (String, (CHAR8 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINT64, + then MAX_UINT64 is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrHexToUint64 ( + IN CONST CHAR8 *String + ) +{ + UINT64 Result; + + AsciiStrHexToUint64S (String, (CHAR8 **) NULL, &Result); + return Result; +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is deprecated for security reason. + + Convert one Null-terminated ASCII string to a Null-terminated + Unicode string and returns the Unicode string. + + This function converts the contents of the ASCII string Source to the Unicode + string Destination, and returns Destination. The function terminates the + Unicode string Destination by appending a Null-terminator character at the end. + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param Source A pointer to a Null-terminated ASCII string. + @param Destination A pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +AsciiStrToUnicodeStr ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination + ) +{ + CHAR16 *ReturnValue; + + ASSERT (Destination != NULL); + + // + // ASSERT Source is less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (Source) != 0); + + // + // Source and Destination should not overlap + // + ASSERT ((UINTN) ((CHAR8 *) Destination - Source) > AsciiStrLen (Source)); + ASSERT ((UINTN) (Source - (CHAR8 *) Destination) >= (AsciiStrSize (Source) * sizeof (CHAR16))); + + + ReturnValue = Destination; + while (*Source != '\0') { + *(Destination++) = (CHAR16)(UINT8) *(Source++); + } + // + // End the Destination with a NULL. + // + *Destination = '\0'; + + // + // ASSERT Original Destination is less long than PcdMaximumUnicodeStringLength + // + ASSERT (StrSize (ReturnValue) != 0); + + return ReturnValue; +} + +#endif + +STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +/** + Convert binary data to a Base64 encoded ascii string based on RFC4648. + + Produce a Null-terminated Ascii string in the output buffer specified by Destination and DestinationSize. + The Ascii string is produced by converting the data string specified by Source and SourceLength. + + @param Source Input UINT8 data + @param SourceLength Number of UINT8 bytes of data + @param Destination Pointer to output string buffer + @param DestinationSize Size of ascii buffer. Set to 0 to get the size needed. + Caller is responsible for passing in buffer of DestinationSize + + @retval RETURN_SUCCESS When ascii buffer is filled in. + @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL. + @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS - (UINTN)Destination). + @retval RETURN_BUFFER_TOO_SMALL If SourceLength is 0 and DestinationSize is <1. + @retval RETURN_BUFFER_TOO_SMALL If Destination is NULL or DestinationSize is smaller than required buffersize. + +**/ +RETURN_STATUS +EFIAPI +Base64Encode ( + IN CONST UINT8 *Source, + IN UINTN SourceLength, + OUT CHAR8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize + ) +{ + + UINTN RequiredSize; + UINTN Left; + + // + // Check pointers, and SourceLength is valid + // + if ((Source == NULL) || (DestinationSize == NULL)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Allow for RFC 4648 test vector 1 + // + if (SourceLength == 0) { + if (*DestinationSize < 1) { + *DestinationSize = 1; + return RETURN_BUFFER_TOO_SMALL; + } + *DestinationSize = 1; + *Destination = '\0'; + return RETURN_SUCCESS; + } + + // + // Check if SourceLength or DestinationSize is valid + // + if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))){ + return RETURN_INVALID_PARAMETER; + } + + // + // 4 ascii per 3 bytes + NULL + // + RequiredSize = ((SourceLength + 2) / 3) * 4 + 1; + if ((Destination == NULL) || *DestinationSize < RequiredSize) { + *DestinationSize = RequiredSize; + return RETURN_BUFFER_TOO_SMALL; + } + + Left = SourceLength; + + // + // Encode 24 bits (three bytes) into 4 ascii characters + // + while (Left >= 3) { + + *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2 ]; + *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)]; + *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2) + ((Source[2] & 0xc0) >> 6)]; + *Destination++ = EncodingTable[( Source[2] & 0x3f)]; + Left -= 3; + Source += 3; + } + + // + // Handle the remainder, and add padding '=' characters as necessary. + // + switch (Left) { + case 0: + + // + // No bytes Left, done. + // + break; + case 1: + + // + // One more data byte, two pad characters + // + *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2]; + *Destination++ = EncodingTable[((Source[0] & 0x03) << 4)]; + *Destination++ = '='; + *Destination++ = '='; + break; + case 2: + + // + // Two more data bytes, and one pad character + // + *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2]; + *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)]; + *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2)]; + *Destination++ = '='; + break; + } + // + // Add terminating NULL + // + *Destination = '\0'; + return RETURN_SUCCESS; +} + +/** + Decode Base64 ASCII encoded data to 8-bit binary representation, based on + RFC4648. + + Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648. + + Whitespace is ignored at all positions: + - 0x09 ('\t') horizontal tab + - 0x0A ('\n') new line + - 0x0B ('\v') vertical tab + - 0x0C ('\f') form feed + - 0x0D ('\r') carriage return + - 0x20 (' ') space + + The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated + and enforced at the end of the Base64 ASCII encoded data, and only there. + + Other characters outside of the encoding alphabet cause the function to + reject the Base64 ASCII encoded data. + + @param[in] Source Array of CHAR8 elements containing the Base64 + ASCII encoding. May be NULL if SourceSize is + zero. + + @param[in] SourceSize Number of CHAR8 elements in Source. + + @param[out] Destination Array of UINT8 elements receiving the decoded + 8-bit binary representation. Allocated by the + caller. May be NULL if DestinationSize is + zero on input. If NULL, decoding is + performed, but the 8-bit binary + representation is not stored. If non-NULL and + the function returns an error, the contents + of Destination are indeterminate. + + @param[in,out] DestinationSize On input, the number of UINT8 elements that + the caller allocated for Destination. On + output, if the function returns + RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL, + the number of UINT8 elements that are + required for decoding the Base64 ASCII + representation. If the function returns a + value different from both RETURN_SUCCESS and + RETURN_BUFFER_TOO_SMALL, then DestinationSize + is indeterminate on output. + + @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have + been decoded to on-output DestinationSize + UINT8 elements at Destination. Note that + RETURN_SUCCESS covers the case when + DestinationSize is zero on input, and + Source decodes to zero bytes (due to + containing at most ignored whitespace). + + @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not + large enough for decoding SourceSize CHAR8 + elements at Source. The required number of + UINT8 elements has been stored to + DestinationSize. + + @retval RETURN_INVALID_PARAMETER DestinationSize is NULL. + + @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero. + + @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is + not zero on input. + + @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source + + SourceSize) would wrap around MAX_ADDRESS. + + @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination + + DestinationSize) would wrap around + MAX_ADDRESS, as specified on input. + + @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL, + and CHAR8[SourceSize] at Source overlaps + UINT8[DestinationSize] at Destination, as + specified on input. + + @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in + Source. +**/ +RETURN_STATUS +EFIAPI +Base64Decode ( + IN CONST CHAR8 *Source OPTIONAL, + IN UINTN SourceSize, + OUT UINT8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize + ) +{ + BOOLEAN PaddingMode; + UINTN SixBitGroupsConsumed; + UINT32 Accumulator; + UINTN OriginalDestinationSize; + UINTN SourceIndex; + CHAR8 SourceChar; + UINT32 Base64Value; + UINT8 DestinationOctet; + + if (DestinationSize == NULL) { + return RETURN_INVALID_PARAMETER; + } + + // + // Check Source array validity. + // + if (Source == NULL) { + if (SourceSize > 0) { + // + // At least one CHAR8 element at NULL Source. + // + return RETURN_INVALID_PARAMETER; + } + } else if (SourceSize > MAX_ADDRESS - (UINTN)Source) { + // + // Non-NULL Source, but it wraps around. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Check Destination array validity. + // + if (Destination == NULL) { + if (*DestinationSize > 0) { + // + // At least one UINT8 element at NULL Destination. + // + return RETURN_INVALID_PARAMETER; + } + } else if (*DestinationSize > MAX_ADDRESS - (UINTN)Destination) { + // + // Non-NULL Destination, but it wraps around. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Check for overlap. + // + if (Source != NULL && Destination != NULL) { + // + // Both arrays have been provided, and we know from earlier that each array + // is valid in itself. + // + if ((UINTN)Source + SourceSize <= (UINTN)Destination) { + // + // Source array precedes Destination array, OK. + // + } else if ((UINTN)Destination + *DestinationSize <= (UINTN)Source) { + // + // Destination array precedes Source array, OK. + // + } else { + // + // Overlap. + // + return RETURN_INVALID_PARAMETER; + } + } + + // + // Decoding loop setup. + // + PaddingMode = FALSE; + SixBitGroupsConsumed = 0; + Accumulator = 0; + OriginalDestinationSize = *DestinationSize; + *DestinationSize = 0; + + // + // Decoding loop. + // + for (SourceIndex = 0; SourceIndex < SourceSize; SourceIndex++) { + SourceChar = Source[SourceIndex]; + + // + // Whitespace is ignored at all positions (regardless of padding mode). + // + if (SourceChar == '\t' || SourceChar == '\n' || SourceChar == '\v' || + SourceChar == '\f' || SourceChar == '\r' || SourceChar == ' ') { + continue; + } + + // + // If we're in padding mode, accept another padding character, as long as + // that padding character completes the quantum. This completes case (2) + // from RFC4648, Chapter 4. "Base 64 Encoding": + // + // (2) The final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by two + // "=" padding characters. + // + if (PaddingMode) { + if (SourceChar == '=' && SixBitGroupsConsumed == 3) { + SixBitGroupsConsumed = 0; + continue; + } + return RETURN_INVALID_PARAMETER; + } + + // + // When not in padding mode, decode Base64Value based on RFC4648, "Table 1: + // The Base 64 Alphabet". + // + if ('A' <= SourceChar && SourceChar <= 'Z') { + Base64Value = SourceChar - 'A'; + } else if ('a' <= SourceChar && SourceChar <= 'z') { + Base64Value = 26 + (SourceChar - 'a'); + } else if ('0' <= SourceChar && SourceChar <= '9') { + Base64Value = 52 + (SourceChar - '0'); + } else if (SourceChar == '+') { + Base64Value = 62; + } else if (SourceChar == '/') { + Base64Value = 63; + } else if (SourceChar == '=') { + // + // Enter padding mode. + // + PaddingMode = TRUE; + + if (SixBitGroupsConsumed == 2) { + // + // If we have consumed two 6-bit groups from the current quantum before + // encountering the first padding character, then this is case (2) from + // RFC4648, Chapter 4. "Base 64 Encoding". Bump SixBitGroupsConsumed, + // and we'll enforce another padding character. + // + SixBitGroupsConsumed = 3; + } else if (SixBitGroupsConsumed == 3) { + // + // If we have consumed three 6-bit groups from the current quantum + // before encountering the first padding character, then this is case + // (3) from RFC4648, Chapter 4. "Base 64 Encoding". The quantum is now + // complete. + // + SixBitGroupsConsumed = 0; + } else { + // + // Padding characters are not allowed at the first two positions of a + // quantum. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Wherever in a quantum we enter padding mode, we enforce the padding + // bits pending in the accumulator -- from the last 6-bit group just + // preceding the padding character -- to be zero. Refer to RFC4648, + // Chapter 3.5. "Canonical Encoding". + // + if (Accumulator != 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // Advance to the next source character. + // + continue; + } else { + // + // Other characters outside of the encoding alphabet are rejected. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Feed the bits of the current 6-bit group of the quantum to the + // accumulator. + // + Accumulator = (Accumulator << 6) | Base64Value; + SixBitGroupsConsumed++; + switch (SixBitGroupsConsumed) { + case 1: + // + // No octet to spill after consuming the first 6-bit group of the + // quantum; advance to the next source character. + // + continue; + case 2: + // + // 12 bits accumulated (6 pending + 6 new); prepare for spilling an + // octet. 4 bits remain pending. + // + DestinationOctet = (UINT8)(Accumulator >> 4); + Accumulator &= 0xF; + break; + case 3: + // + // 10 bits accumulated (4 pending + 6 new); prepare for spilling an + // octet. 2 bits remain pending. + // + DestinationOctet = (UINT8)(Accumulator >> 2); + Accumulator &= 0x3; + break; + default: + ASSERT (SixBitGroupsConsumed == 4); + // + // 8 bits accumulated (2 pending + 6 new); prepare for spilling an octet. + // The quantum is complete, 0 bits remain pending. + // + DestinationOctet = (UINT8)Accumulator; + Accumulator = 0; + SixBitGroupsConsumed = 0; + break; + } + + // + // Store the decoded octet if there's room left. Increment + // (*DestinationSize) unconditionally. + // + if (*DestinationSize < OriginalDestinationSize) { + ASSERT (Destination != NULL); + Destination[*DestinationSize] = DestinationOctet; + } + (*DestinationSize)++; + + // + // Advance to the next source character. + // + } + + // + // If Source terminates mid-quantum, then Source is invalid. + // + if (SixBitGroupsConsumed != 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // Done. + // + if (*DestinationSize <= OriginalDestinationSize) { + return RETURN_SUCCESS; + } + return RETURN_BUFFER_TOO_SMALL; +} + +/** + Converts an 8-bit value to an 8-bit BCD value. + + Converts the 8-bit value specified by Value to BCD. The BCD value is + returned. + + If Value >= 100, then ASSERT(). + + @param Value The 8-bit value to convert to BCD. Range 0..99. + + @return The BCD value. + +**/ +UINT8 +EFIAPI +DecimalToBcd8 ( + IN UINT8 Value + ) +{ + ASSERT (Value < 100); + return (UINT8) (((Value / 10) << 4) | (Value % 10)); +} + +/** + Converts an 8-bit BCD value to an 8-bit value. + + Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit + value is returned. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Value The 8-bit BCD value to convert to an 8-bit value. + + @return The 8-bit value is returned. + +**/ +UINT8 +EFIAPI +BcdToDecimal8 ( + IN UINT8 Value + ) +{ + ASSERT (Value < 0xa0); + ASSERT ((Value & 0xf) < 0xa); + return (UINT8) ((Value >> 4) * 10 + (Value & 0xf)); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/SwapBytes16.c b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes16.c new file mode 100644 index 000000000..52e7f71d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes16.c @@ -0,0 +1,33 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 16-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Value + ) +{ + return (UINT16) ((Value<< 8) | (Value>> 8)); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/SwapBytes32.c b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes32.c new file mode 100644 index 000000000..5109ad512 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes32.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 32-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Value + ) +{ + UINT32 LowerBytes; + UINT32 HigherBytes; + + LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value); + HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16)); + + return (LowerBytes << 16 | HigherBytes); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/SwapBytes64.c b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes64.c new file mode 100644 index 000000000..500f76d48 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SwapBytes64.c @@ -0,0 +1,33 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 64-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Value + ) +{ + return InternalMathSwapBytes64 (Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/SwitchStack.c b/roms/edk2/MdePkg/Library/BaseLib/SwitchStack.c new file mode 100644 index 000000000..cb9f69f1e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/SwitchStack.c @@ -0,0 +1,70 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. This function + supports a variable number of arguments following the NewStack parameter. + These additional arguments are ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param ... This variable argument list is ignored for IA32, x64, and EBC. + For IPF, this variable argument list is expected to contain + a single parameter of type VOID * that specifies the new backing + store pointer. + + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + ... + ) +{ + VA_LIST Marker; + + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + + // + // New stack must be aligned with CPU_STACK_ALIGNMENT + // + ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); + + VA_START (Marker, NewStack); + + InternalSwitchStack (EntryPoint, Context1, Context2, NewStack, Marker); + + VA_END (Marker); + + // + // InternalSwitchStack () will never return + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/Unaligned.c b/roms/edk2/MdePkg/Library/BaseLib/Unaligned.c new file mode 100644 index 000000000..a419cb85e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/Unaligned.c @@ -0,0 +1,216 @@ +/** @file + Unaligned access functions of BaseLib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 16-bit value that may be unaligned. + + @return The 16-bit value read from Buffer. + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return The 16-bit value to write to Buffer. + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 24-bit value that may be unaligned. + + @return The 24-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer & 0xffffff; +} + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The 24-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + *Buffer = BitFieldWrite32 (*Buffer, 0, 23, Value); + return Value; +} + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 32-bit value that may be unaligned. + + @return The 32-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 32-bit value that may be unaligned. + @param Value The 32-bit value to write to Buffer. + + @return The 32-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 64-bit value that may be unaligned. + + @return The 64-bit value read from Buffer. + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 64-bit value that may be unaligned. + @param Value The 64-bit value to write to Buffer. + + @return The 64-bit value to write to Buffer. + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.c b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.c new file mode 100644 index 000000000..79eec7cac --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.c @@ -0,0 +1,140 @@ +/** @file + Common Unit Test Host functions. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestHost.h" + +/// +/// Module global variable for simple system emulation of interrupt state +/// +STATIC BOOLEAN mUnitTestHostBaseLibInterruptState; + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibEnableInterrupts ( + VOID + ) +{ + mUnitTestHostBaseLibInterruptState = TRUE; +} + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibDisableInterrupts ( + VOID + ) +{ + mUnitTestHostBaseLibInterruptState = FALSE; +} + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibEnableDisableInterrupts ( + VOID + ) +{ + mUnitTestHostBaseLibInterruptState = FALSE; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +UnitTestHostBaseLibGetInterruptState ( + VOID + ) +{ + return mUnitTestHostBaseLibInterruptState; +} + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + gUnitTestHostBaseLib.Common->EnableInterrupts (); +} + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + gUnitTestHostBaseLib.Common->DisableInterrupts (); +} + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ) +{ + gUnitTestHostBaseLib.Common->EnableDisableInterrupts (); +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + return gUnitTestHostBaseLib.Common->GetInterruptState (); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.h b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.h new file mode 100644 index 000000000..42bc6b777 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHost.h @@ -0,0 +1,66 @@ +/** @file + Unit Test Host functions. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __UNIT_TEST_HOST_H__ +#define __UNIT_TEST_HOST_H__ + +#include "BaseLibInternals.h" +#include + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibEnableInterrupts ( + VOID + ); + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibDisableInterrupts ( + VOID + ); + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibEnableDisableInterrupts ( + VOID + ); + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +UnitTestHostBaseLibGetInterruptState ( + VOID + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf new file mode 100644 index 000000000..eae1a7158 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf @@ -0,0 +1,251 @@ +## @file +# Base Library implementation for use with host based unit tests. +# +# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UnitTestHostBaseLib + MODULE_UNI_FILE = UnitTestHostBaseLib.uni + FILE_GUID = 9555A0D3-09BA-46C4-A51A-45198E3C765E + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = BaseLib|HOST_APPLICATION + LIBRARY_CLASS = UnitTestHostBaseLib|HOST_APPLICATION + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources] + CheckSum.c + SwitchStack.c + SwapBytes64.c + SwapBytes32.c + SwapBytes16.c + LongJump.c + SetJump.c + RShiftU64.c + RRotU64.c + RRotU32.c + MultU64x64.c + MultU64x32.c + MultS64x64.c + ModU64x32.c + LShiftU64.c + LRotU64.c + LRotU32.c + LowBitSet64.c + LowBitSet32.c + HighBitSet64.c + HighBitSet32.c + GetPowerOfTwo64.c + GetPowerOfTwo32.c + DivU64x64Remainder.c + DivU64x32Remainder.c + DivU64x32.c + DivS64x64Remainder.c + ARShiftU64.c + BitField.c + CpuDeadLoop.c + Cpu.c + LinkedList.c + SafeString.c + String.c + FilePaths.c + BaseLibInternals.h + UnitTestHost.c + UnitTestHost.h + +[Sources.Ia32] + Ia32/WriteMm7.c | MSFT + Ia32/WriteMm6.c | MSFT + Ia32/WriteMm5.c | MSFT + Ia32/WriteMm4.c | MSFT + Ia32/WriteMm3.c | MSFT + Ia32/WriteMm2.c | MSFT + Ia32/WriteMm1.c | MSFT + Ia32/WriteMm0.c | MSFT + Ia32/ReadMm7.c | MSFT + Ia32/ReadMm6.c | MSFT + Ia32/ReadMm5.c | MSFT + Ia32/ReadMm4.c | MSFT + Ia32/ReadMm3.c | MSFT + Ia32/ReadMm2.c | MSFT + Ia32/ReadMm1.c | MSFT + Ia32/ReadMm0.c | MSFT + Ia32/SwapBytes64.c | MSFT + Ia32/RRotU64.c | MSFT + Ia32/RShiftU64.c | MSFT + Ia32/ReadTsc.c | MSFT + Ia32/ReadEflags.c | MSFT + Ia32/ModU64x32.c | MSFT + Ia32/MultU64x64.c | MSFT + Ia32/MultU64x32.c | MSFT + Ia32/LShiftU64.c | MSFT + Ia32/LRotU64.c | MSFT + Ia32/FxRestore.c | MSFT + Ia32/FxSave.c | MSFT + Ia32/DivU64x32Remainder.c | MSFT + Ia32/DivU64x32.c | MSFT + Ia32/CpuPause.c | MSFT + Ia32/CpuBreakpoint.c | MSFT + Ia32/ARShiftU64.c | MSFT + Ia32/GccInline.c | GCC + Ia32/LongJump.nasm + Ia32/SetJump.nasm + Ia32/SwapBytes64.nasm| GCC + Ia32/DivU64x64Remainder.nasm + Ia32/DivU64x32Remainder.nasm| GCC + Ia32/ModU64x32.nasm| GCC + Ia32/DivU64x32.nasm| GCC + Ia32/MultU64x64.nasm| GCC + Ia32/MultU64x32.nasm| GCC + Ia32/RRotU64.nasm| GCC + Ia32/LRotU64.nasm| GCC + Ia32/ARShiftU64.nasm| GCC + Ia32/RShiftU64.nasm| GCC + Ia32/LShiftU64.nasm| GCC + Ia32/RdRand.nasm + Ia32/DivS64x64Remainder.c + Ia32/InternalSwitchStack.c | MSFT + Ia32/InternalSwitchStack.nasm | GCC + Ia32/Non-existing.c + Unaligned.c + X86MemoryFence.c | MSFT + X86FxSave.c + X86FxRestore.c + X86Msr.c + X86RdRand.c + X86SpeculationBarrier.c + X86UnitTestHost.c + +[Sources.X64] + X64/LongJump.nasm + X64/SetJump.nasm + X64/SwitchStack.nasm + X64/CpuBreakpoint.c | MSFT + X64/CpuPause.nasm| MSFT + X64/ReadTsc.nasm| MSFT + X64/WriteMm7.nasm| MSFT + X64/WriteMm6.nasm| MSFT + X64/WriteMm5.nasm| MSFT + X64/WriteMm4.nasm| MSFT + X64/WriteMm3.nasm| MSFT + X64/WriteMm2.nasm| MSFT + X64/WriteMm1.nasm| MSFT + X64/WriteMm0.nasm| MSFT + X64/ReadMm7.nasm| MSFT + X64/ReadMm6.nasm| MSFT + X64/ReadMm5.nasm| MSFT + X64/ReadMm4.nasm| MSFT + X64/ReadMm3.nasm| MSFT + X64/ReadMm2.nasm| MSFT + X64/ReadMm1.nasm| MSFT + X64/ReadMm0.nasm| MSFT + X64/FxRestore.nasm| MSFT + X64/FxSave.nasm| MSFT + X64/ReadEflags.nasm| MSFT + X64/Non-existing.c + Math64.c + Unaligned.c + X86MemoryFence.c | MSFT + X86FxSave.c + X86FxRestore.c + X86Msr.c + X86RdRand.c + X86SpeculationBarrier.c + X64/GccInline.c | GCC + X64/RdRand.nasm + ChkStkGcc.c | GCC + X86UnitTestHost.c + +[Sources.EBC] + Ebc/CpuBreakpoint.c + Ebc/SetJumpLongJump.c + Ebc/SwitchStack.c + Ebc/SpeculationBarrier.c + Unaligned.c + Math64.c + +[Sources.ARM] + Arm/InternalSwitchStack.c + Arm/Unaligned.c + Math64.c | RVCT + Math64.c | MSFT + + Arm/SwitchStack.asm | RVCT + Arm/SetJumpLongJump.asm | RVCT + Arm/CpuPause.asm | RVCT + Arm/CpuBreakpoint.asm | RVCT + Arm/MemoryFence.asm | RVCT + Arm/SpeculationBarrier.S | RVCT + + Arm/SwitchStack.asm | MSFT + Arm/SetJumpLongJump.asm | MSFT + Arm/CpuPause.asm | MSFT + Arm/CpuBreakpoint.asm | MSFT + Arm/MemoryFence.asm | MSFT + Arm/SpeculationBarrier.asm | MSFT + + Arm/Math64.S | GCC + Arm/SwitchStack.S | GCC + Arm/SetJumpLongJump.S | GCC + Arm/CpuBreakpoint.S | GCC + Arm/MemoryFence.S | GCC + Arm/SpeculationBarrier.S | GCC + +[Sources.AARCH64] + Arm/InternalSwitchStack.c + Arm/Unaligned.c + Math64.c + + AArch64/MemoryFence.S | GCC + AArch64/SwitchStack.S | GCC + AArch64/SetJumpLongJump.S | GCC + AArch64/CpuBreakpoint.S | GCC + AArch64/SpeculationBarrier.S | GCC + + AArch64/MemoryFence.asm | MSFT + AArch64/SwitchStack.asm | MSFT + AArch64/SetJumpLongJump.asm | MSFT + AArch64/CpuBreakpoint.asm | MSFT + AArch64/SpeculationBarrier.asm | MSFT + +[Sources.RISCV64] + Math64.c + Unaligned.c + RiscV64/InternalSwitchStack.c + RiscV64/CpuBreakpoint.c + RiscV64/CpuPause.c + RiscV64/RiscVSetJumpLongJump.S | GCC + RiscV64/RiscVCpuBreakpoint.S | GCC + RiscV64/RiscVCpuPause.S | GCC + RiscV64/RiscVInterrupt.S | GCC + RiscV64/FlushCache.S | GCC + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + DebugLib + BaseMemoryLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdSpeculationBarrierType ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni new file mode 100644 index 000000000..e63ecef82 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni @@ -0,0 +1,11 @@ +// /** @file +// Base Library implementation for use with host based unit tests. +// +// Copyright (c) 2020, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Base Library implementation for use with host based unit tests." + +#string STR_MODULE_DESCRIPTION #language en-US "Base Library implementation for use with host based unit tests." diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c new file mode 100644 index 000000000..c626ef8ec --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c @@ -0,0 +1,33 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +void __debugbreak (VOID); + +#pragma intrinsic(__debugbreak) + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __debugbreak (); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm new file mode 100644 index 000000000..5bdbe3290 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuBreakpoint.Asm +; +; Abstract: +; +; CpuBreakpoint function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuBreakpoint ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuBreakpoint) +ASM_PFX(CpuBreakpoint): + int 3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm new file mode 100644 index 000000000..bb83017c8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmCpuid ( +; IN UINT32 RegisterInEax, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(AsmCpuid) +ASM_PFX(AsmCpuid): + push rbx + mov eax, ecx + push rax ; save Index on stack + push rdx + cpuid + test r9, r9 + jz .0 + mov [r9], ecx +.0: + pop rcx + jrcxz .1 + mov [rcx], eax +.1: + mov rcx, r8 + jrcxz .2 + mov [rcx], ebx +.2: + mov rcx, [rsp + 0x38] + jrcxz .3 + mov [rcx], edx +.3: + pop rax ; restore Index to rax as return value + pop rbx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm new file mode 100644 index 000000000..fd5caa328 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm @@ -0,0 +1,60 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuIdEx.Asm +; +; Abstract: +; +; AsmCpuidEx function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmCpuidEx ( +; IN UINT32 RegisterInEax, +; IN UINT32 RegisterInEcx, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(AsmCpuidEx) +ASM_PFX(AsmCpuidEx): + push rbx + mov eax, ecx + mov ecx, edx + push rax ; save Index on stack + cpuid + mov r10, [rsp + 0x38] + test r10, r10 + jz .0 + mov [r10], ecx +.0: + mov rcx, r8 + jrcxz .1 + mov [rcx], eax +.1: + mov rcx, r9 + jrcxz .2 + mov [rcx], ebx +.2: + mov rcx, [rsp + 0x40] + jrcxz .3 + mov [rcx], edx +.3: + pop rax ; restore Index to rax as return value + pop rbx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm new file mode 100644 index 000000000..ca3519741 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CpuPause.Asm +; +; Abstract: +; +; CpuPause function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuPause ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(CpuPause) +ASM_PFX(CpuPause): + pause + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm new file mode 100644 index 000000000..93f5f7539 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisableCache.Asm +; +; Abstract: +; +; Set the CD bit of CR0 to 1, clear the NW bit of CR0 to 0, and flush all caches with a +; WBINVD instruction. +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmDisableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmDisableCache) +ASM_PFX(AsmDisableCache): + mov rax, cr0 + bts rax, 30 + btr rax, 29 + mov cr0, rax + wbinvd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm new file mode 100644 index 000000000..43c7e5d02 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisableInterrupts.Asm +; +; Abstract: +; +; DisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; DisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(DisableInterrupts) +ASM_PFX(DisableInterrupts): + cli + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm new file mode 100644 index 000000000..c76ed1a76 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; DisablePaging64.Asm +; +; Abstract: +; +; AsmDisablePaging64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86DisablePaging64 ( +; IN UINT16 Cs, +; IN UINT32 EntryPoint, +; IN UINT32 Context1, OPTIONAL +; IN UINT32 Context2, OPTIONAL +; IN UINT32 NewStack +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86DisablePaging64) +ASM_PFX(InternalX86DisablePaging64): + cli + lea rsi, [.0] ; rsi <- The start address of transition code + mov edi, [rsp + 0x28] ; rdi <- New stack + lea rax, [mTransitionEnd] ; rax <- end of transition code + sub rax, rsi ; rax <- The size of transition piece code + add rax, 4 ; Round RAX up to the next 4 byte boundary + and al, 0xfc + sub rdi, rax ; rdi <- Use stack to hold transition code + mov r10d, edi ; r10 <- The start address of transicition code below 4G + push rcx ; save rcx to stack + mov rcx, rax ; rcx <- The size of transition piece code + rep movsb ; copy transition code to top of new stack which must be below 4GB + pop rcx ; restore rcx + + mov esi, r8d + mov edi, r9d + mov eax, r10d ; eax <- start of the transition code on the stack + sub eax, 4 ; eax <- One slot below transition code on the stack + push rcx ; push Cs to stack + push r10 ; push address of tansition code on stack + DB 0x48 ; prefix to composite "retq" with next "retf" + retf ; Use far return to load CS register from stack + +; Start of transition code +.0: + mov esp, eax ; set up new stack + mov rax, cr0 + btr eax, 31 ; Clear CR0.PG + mov cr0, rax ; disable paging and caches + + mov ebx, edx ; save EntryPoint to rbx, for rdmsr will overwrite rdx + mov ecx, 0xc0000080 + rdmsr + and ah, ~ 1 ; clear LME + wrmsr + mov rax, cr4 + and al, ~ (1 << 5) ; clear PAE + mov cr4, rax + push rdi ; push Context2 + push rsi ; push Context1 + call rbx ; transfer control to EntryPoint + hlt ; no one should get here + +mTransitionEnd: + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm new file mode 100644 index 000000000..b6fae3cbf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableCache.Asm +; +; Abstract: +; +; Flush all caches with a WBINVD instruction, clear the CD bit of CR0 to 0, and clear +; the NW bit of CR0 to 0 +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmEnableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmEnableCache) +ASM_PFX(AsmEnableCache): + wbinvd + mov rax, cr0 + btr rax, 29 + btr rax, 30 + mov cr0, rax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm new file mode 100644 index 000000000..3c7e9e78d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableDisableInterrupts.Asm +; +; Abstract: +; +; EnableDisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableDisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(EnableDisableInterrupts) +ASM_PFX(EnableDisableInterrupts): + sti + cli + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm new file mode 100644 index 000000000..6057afd62 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; EnableInterrupts.Asm +; +; Abstract: +; +; EnableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(EnableInterrupts) +ASM_PFX(EnableInterrupts): + sti + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm new file mode 100644 index 000000000..1effabe0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FlushCacheLine.Asm +; +; Abstract: +; +; AsmFlushCacheLine function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; AsmFlushCacheLine ( +; IN VOID *LinearAddress +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmFlushCacheLine) +ASM_PFX(AsmFlushCacheLine): + clflush [rcx] + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm new file mode 100644 index 000000000..261981edf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FxRestore.Asm +; +; Abstract: +; +; AsmFxRestore function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxRestore ( +; IN CONST IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86FxRestore) +ASM_PFX(InternalX86FxRestore): + fxrstor [rcx] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm new file mode 100644 index 000000000..fafe24d62 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; FxSave.Asm +; +; Abstract: +; +; AsmFxSave function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxSave ( +; OUT IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86FxSave) +ASM_PFX(InternalX86FxSave): + fxsave [rcx] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/GccInline.c b/roms/edk2/MdePkg/Library/BaseLib/X64/GccInline.c new file mode 100644 index 000000000..40a208f19 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/GccInline.c @@ -0,0 +1,562 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions. + + Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + // This is a little bit of overkill and it is more about the compiler that it is + // actually processor synchronization. This is like the _ReadWriteBarrier + // Microsoft specific intrinsic + __asm__ __volatile__ ("":::"memory"); +} + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + __asm__ __volatile__ ("pause"); +} + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __asm__ __volatile__ ("int $3"); +} + + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ) +{ + UINTN Eflags; + + __asm__ __volatile__ ( + "pushfq \n\t" + "pop %0 " + : "=r" (Eflags) // %0 + ); + + return Eflags; +} + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxsave %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxrstor %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and X64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm0, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and X64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm1, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and X64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm2, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and X64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm3, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and X64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm4, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and X64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm5, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and X64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm6, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and X64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "movd %%mm7, %0 \n\t" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm0" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm1" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm2" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm3" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm4" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm5" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm6" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movd %0, %%mm7" // %0 + : + : "m" (Value) + ); +} + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and X64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ) +{ + UINT32 LowData; + UINT32 HiData; + + __asm__ __volatile__ ( + "rdtsc" + : "=a" (LowData), + "=d" (HiData) + ); + + return (((UINT64)HiData) << 32) | LowData; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/GccInlinePriv.c b/roms/edk2/MdePkg/Library/BaseLib/X64/GccInlinePriv.c new file mode 100644 index 000000000..98be19b3c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/GccInlinePriv.c @@ -0,0 +1,1234 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions that use + privlidged instructions. + + Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + UINT32 LowData; + UINT32 HighData; + + __asm__ __volatile__ ( + "rdmsr" + : "=a" (LowData), // %0 + "=d" (HighData) // %1 + : "c" (Index) // %2 + ); + + return (((UINT64)HighData) << 32) | LowData; +} + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + UINT32 LowData; + UINT32 HighData; + + LowData = (UINT32)(Value); + HighData = (UINT32)(Value >> 32); + + __asm__ __volatile__ ( + "wrmsr" + : + : "c" (Index), + "a" (LowData), + "d" (HighData) + ); + + return Value; +} + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%cr0,%0" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%cr2, %0" + : "=r" (Data) // %0 + ); + + return Data; +} + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%cr3, %0" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%cr4, %0" + : "=r" (Data) // %0 + ); + + return Data; +} + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%cr0" + : + : "r" (Cr0) + ); + return Cr0; +} + + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%cr2" + : + : "r" (Cr2) + ); + return Cr2; +} + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%cr3" + : + : "r" (Cr3) + ); + return Cr3; +} + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%cr4" + : + : "r" (Cr4) + ); + return Cr4; +} + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr0, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr1, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr2, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr3, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr4, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr5, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr6, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "mov %%dr7, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr0" + : + : "r" (Dr0) + ); + return Dr0; +} + + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr1" + : + : "r" (Dr1) + ); + return Dr1; +} + + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr2" + : + : "r" (Dr2) + ); + return Dr2; +} + + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr3" + : + : "r" (Dr3) + ); + return Dr3; +} + + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr4" + : + : "r" (Dr4) + ); + return Dr4; +} + + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr5" + : + : "r" (Dr5) + ); + return Dr5; +} + + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr6" + : + : "r" (Dr6) + ); + return Dr6; +} + + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ) +{ + __asm__ __volatile__ ( + "mov %0, %%dr7" + : + : "r" (Dr7) + ); + return Dr7; +} + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and X64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%cs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and X64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and X64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%es, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and X64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%fs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and X64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%gs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and X64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and X64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "str %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "sgdt %0" + : "=m" (*Gdtr) + ); +} + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "lgdt %0" + : + : "m" (*Gdtr) + ); + +} + + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "sidt %0" + : "=m" (*Idtr) + ); +} + + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "lidt %0" + : + : "m" (*Idtr) + ); +} + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and X64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "sldt %0" + : "=g" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current Local Descriptor Table Register (GDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and X64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + __asm__ __volatile__ ( + "lldtw %0" + : + : "g" (Ldtr) // %0 + ); +} + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and X64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ) +{ + UINT32 LowData; + UINT32 HiData; + + __asm__ __volatile__ ( + "rdpmc" + : "=a" (LowData), + "=d" (HiData) + : "c" (Index) + ); + + return (((UINT64)HiData) << 32) | LowData; +} + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and X64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ) +{ + __asm__ __volatile__ ( + "monitor" + : + : "a" (Eax), + "c" (Ecx), + "d" (Edx) + ); + + return Eax; +} + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and X64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ) +{ + __asm__ __volatile__ ( + "mwait" + : + : "a" (Eax), + "c" (Ecx) + ); + + return Eax; +} + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ) +{ + __asm__ __volatile__ ("wbinvd":::"memory"); +} + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ) +{ + __asm__ __volatile__ ("invd":::"memory"); + +} + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and X64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + __asm__ __volatile__ ( + "clflush (%0)" + : + : "r" (LinearAddress) + : "memory" + ); + + return LinearAddress; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm new file mode 100644 index 000000000..5580f64c5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Invd.Asm +; +; Abstract: +; +; AsmInvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmInvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmInvd) +ASM_PFX(AsmInvd): + invd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm new file mode 100644 index 000000000..25fd0746a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2018, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Lfence.nasm +; +; Abstract: +; +; Performs a serializing operation on all load-from-memory instructions that +; were issued prior to the call of this function. +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmLfence ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmLfence) +ASM_PFX(AsmLfence): + lfence + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm new file mode 100644 index 000000000..59f709216 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; LongJump.Asm +; +; Abstract: +; +; Implementation of _LongJump() on x64. +; +;------------------------------------------------------------------------------ + +%include "Nasm.inc" + + DEFAULT REL + SECTION .text + +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalLongJump ( +; IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalLongJump) +ASM_PFX(InternalLongJump): + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov rax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + push rdx ; save rdx + + mov rdx, [rcx + 0xF8] ; rdx = target SSP + READSSP_RAX + sub rdx, rax ; rdx = delta + mov rax, rdx ; rax = delta + + shr rax, 3 ; rax = delta/sizeof(UINT64) + INCSSP_RAX + + pop rdx ; restore rdx +CetDone: + + mov rbx, [rcx] + mov rsp, [rcx + 8] + mov rbp, [rcx + 0x10] + mov rdi, [rcx + 0x18] + mov rsi, [rcx + 0x20] + mov r12, [rcx + 0x28] + mov r13, [rcx + 0x30] + mov r14, [rcx + 0x38] + mov r15, [rcx + 0x40] + ; load non-volatile fp registers + ldmxcsr [rcx + 0x50] + movdqu xmm6, [rcx + 0x58] + movdqu xmm7, [rcx + 0x68] + movdqu xmm8, [rcx + 0x78] + movdqu xmm9, [rcx + 0x88] + movdqu xmm10, [rcx + 0x98] + movdqu xmm11, [rcx + 0xA8] + movdqu xmm12, [rcx + 0xB8] + movdqu xmm13, [rcx + 0xC8] + movdqu xmm14, [rcx + 0xD8] + movdqu xmm15, [rcx + 0xE8] + mov rax, rdx ; set return value + jmp qword [rcx + 0x48] + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm new file mode 100644 index 000000000..e1ccb83a8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Monitor.Asm +; +; Abstract: +; +; AsmMonitor function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMonitor ( +; IN UINTN Eax, +; IN UINTN Ecx, +; IN UINTN Edx +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmMonitor) +ASM_PFX(AsmMonitor): + mov eax, ecx + mov ecx, edx + mov edx, r8d + DB 0xf, 1, 0xc8 ; monitor + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm new file mode 100644 index 000000000..83fc89549 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Mwait.Asm +; +; Abstract: +; +; AsmMwait function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMwait ( +; IN UINTN Eax, +; IN UINTN Ecx +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmMwait) +ASM_PFX(AsmMwait): + mov eax, ecx + mov ecx, edx + DB 0xf, 1, 0xc9 ; mwait + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c b/roms/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c new file mode 100644 index 000000000..e00cb7eb5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c @@ -0,0 +1,147 @@ +/** @file + Non-existing BaseLib functions on x64 + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +InternalX86EnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + // + // This function cannot work on x64 platform + // + ASSERT (FALSE); +} + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +InternalX86DisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + // + // This function cannot work on x64 platform + // + ASSERT (FALSE); +} + + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +InternalX86EnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + // + // This function cannot work on x64 platform. + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm new file mode 100644 index 000000000..7e7fe9967 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RdRand.nasm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 64-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + ; rdrand ax ; generate a 16 bit RN into eax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn16_ok: + mov [rcx], ax + mov rax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + ; rdrand eax ; generate a 32 bit RN into eax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn32_ok: + mov [rcx], eax + mov rax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through one RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand64 (UINT64 *Random); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + ; rdrand rax ; generate a 64 bit RN into rax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0x48, 0xf, 0xc7, 0xf0 ; rdrand r64: "REX.W + 0f c7 /6 ModRM:r/m(w)" + jc rn64_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn64_ok: + mov [rcx], rax + mov rax, 1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm new file mode 100644 index 000000000..aaa6f81a7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr0.Asm +; +; Abstract: +; +; AsmReadCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr0) +ASM_PFX(AsmReadCr0): + mov rax, cr0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm new file mode 100644 index 000000000..74c4778e1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr2.Asm +; +; Abstract: +; +; AsmReadCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr2) +ASM_PFX(AsmReadCr2): + mov rax, cr2 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm new file mode 100644 index 000000000..ea8173f64 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr3.Asm +; +; Abstract: +; +; AsmReadCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr3) +ASM_PFX(AsmReadCr3): + mov rax, cr3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm new file mode 100644 index 000000000..70c2650ee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCr4.Asm +; +; Abstract: +; +; AsmReadCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCr4) +ASM_PFX(AsmReadCr4): + mov rax, cr4 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm new file mode 100644 index 000000000..ec069b8f5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadCs.Asm +; +; Abstract: +; +; AsmReadCs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadCs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadCs) +ASM_PFX(AsmReadCs): + mov eax, cs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm new file mode 100644 index 000000000..7973e52b6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr0.Asm +; +; Abstract: +; +; AsmReadDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr0) +ASM_PFX(AsmReadDr0): + mov rax, dr0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm new file mode 100644 index 000000000..1a4b15917 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr1.Asm +; +; Abstract: +; +; AsmReadDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr1) +ASM_PFX(AsmReadDr1): + mov rax, dr1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm new file mode 100644 index 000000000..d1e403d6a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr2.Asm +; +; Abstract: +; +; AsmReadDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr2) +ASM_PFX(AsmReadDr2): + mov rax, dr2 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm new file mode 100644 index 000000000..96a9c5b0c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr3.Asm +; +; Abstract: +; +; AsmReadDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr3) +ASM_PFX(AsmReadDr3): + mov rax, dr3 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm new file mode 100644 index 000000000..82c0a9a58 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr4.Asm +; +; Abstract: +; +; AsmReadDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr4) +ASM_PFX(AsmReadDr4): + ; + ; There's no obvious reason to access this register, since it's aliased to + ; DR7 when DE=0 or an exception generated when DE=1 + ; + DB 0xf, 0x21, 0xe0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm new file mode 100644 index 000000000..c309c66df --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr5.Asm +; +; Abstract: +; +; AsmReadDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr5) +ASM_PFX(AsmReadDr5): + ; + ; There's no obvious reason to access this register, since it's aliased to + ; DR7 when DE=0 or an exception generated when DE=1 + ; + DB 0xf, 0x21, 0xe8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm new file mode 100644 index 000000000..7bdc10313 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr6.Asm +; +; Abstract: +; +; AsmReadDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr6) +ASM_PFX(AsmReadDr6): + mov rax, dr6 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm new file mode 100644 index 000000000..219d2e459 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDr7.Asm +; +; Abstract: +; +; AsmReadDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDr7) +ASM_PFX(AsmReadDr7): + mov rax, dr7 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm new file mode 100644 index 000000000..597450d53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadDs.Asm +; +; Abstract: +; +; AsmReadDs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadDs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadDs) +ASM_PFX(AsmReadDs): + mov eax, ds + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm new file mode 100644 index 000000000..e0a5ea065 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadEflags.Asm +; +; Abstract: +; +; AsmReadEflags function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadEflags ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadEflags) +ASM_PFX(AsmReadEflags): + pushfq + pop rax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm new file mode 100644 index 000000000..963394572 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadEs.Asm +; +; Abstract: +; +; AsmReadEs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadEs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadEs) +ASM_PFX(AsmReadEs): + mov eax, es + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm new file mode 100644 index 000000000..9d032ff48 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadFs.Asm +; +; Abstract: +; +; AsmReadFs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadFs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadFs) +ASM_PFX(AsmReadFs): + mov eax, fs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm new file mode 100644 index 000000000..1712c11eb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadGdtr.Asm +; +; Abstract: +; +; AsmReadGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86ReadGdtr ( +; OUT IA32_DESCRIPTOR *Gdtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86ReadGdtr) +ASM_PFX(InternalX86ReadGdtr): + sgdt [rcx] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm new file mode 100644 index 000000000..953fe9c0c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadGs.Asm +; +; Abstract: +; +; AsmReadGs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadGs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadGs) +ASM_PFX(AsmReadGs): + mov eax, gs + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm new file mode 100644 index 000000000..086ab7087 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadIdtr.Asm +; +; Abstract: +; +; AsmReadIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86ReadIdtr ( +; OUT IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86ReadIdtr) +ASM_PFX(InternalX86ReadIdtr): + sidt [rcx] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm new file mode 100644 index 000000000..9339161a3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadLdtr.Asm +; +; Abstract: +; +; AsmReadLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadLdtr ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadLdtr) +ASM_PFX(AsmReadLdtr): + sldt eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm new file mode 100644 index 000000000..615721b6a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm0.Asm +; +; Abstract: +; +; AsmReadMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm0) +ASM_PFX(AsmReadMm0): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xc0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm new file mode 100644 index 000000000..7b2739349 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm1.Asm +; +; Abstract: +; +; AsmReadMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm1) +ASM_PFX(AsmReadMm1): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xc8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm new file mode 100644 index 000000000..c654b91a7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm2.Asm +; +; Abstract: +; +; AsmReadMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm2) +ASM_PFX(AsmReadMm2): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xd0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm new file mode 100644 index 000000000..88d51c078 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm3.Asm +; +; Abstract: +; +; AsmReadMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm3) +ASM_PFX(AsmReadMm3): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xd8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm new file mode 100644 index 000000000..4252d20bb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm4.Asm +; +; Abstract: +; +; AsmReadMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm4) +ASM_PFX(AsmReadMm4): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xe0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm new file mode 100644 index 000000000..d8f530dec --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm5.Asm +; +; Abstract: +; +; AsmReadMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm5) +ASM_PFX(AsmReadMm5): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xe8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm new file mode 100644 index 000000000..6f6883c2b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm6.Asm +; +; Abstract: +; +; AsmReadMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm6) +ASM_PFX(AsmReadMm6): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xf0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm new file mode 100644 index 000000000..573f15dfc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMm7.Asm +; +; Abstract: +; +; AsmReadMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMm7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMm7) +ASM_PFX(AsmReadMm7): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x7e, 0xf8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c new file mode 100644 index 000000000..5ee7ca53f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c @@ -0,0 +1,33 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +unsigned __int64 __readmsr (int register); + +#pragma intrinsic(__readmsr) + +/** + Read data to MSR. + + @param Index Register index of MSR. + + @return Value read from MSR. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + return __readmsr (Index); +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm new file mode 100644 index 000000000..df6925529 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadMsr64.Asm +; +; Abstract: +; +; AsmReadMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMsr64 ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadMsr64) +ASM_PFX(AsmReadMsr64): + rdmsr ; edx & eax are zero extended + shl rdx, 0x20 + or rax, rdx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm new file mode 100644 index 000000000..1785a09de --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadPmc.Asm +; +; Abstract: +; +; AsmReadPmc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadPmc ( +; IN UINT32 PmcIndex +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadPmc) +ASM_PFX(AsmReadPmc): + rdpmc + shl rdx, 0x20 + or rax, rdx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm new file mode 100644 index 000000000..5fbe6985a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadSs.Asm +; +; Abstract: +; +; AsmReadSs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadSs ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadSs) +ASM_PFX(AsmReadSs): + mov eax, ss + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm new file mode 100644 index 000000000..492ef6cd1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTr.Asm +; +; Abstract: +; +; AsmReadTr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadTr ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTr) +ASM_PFX(AsmReadTr): + str eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm new file mode 100644 index 000000000..45672d680 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTsc) +ASM_PFX(AsmReadTsc): + rdtsc + shl rdx, 0x20 + or rax, rdx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm new file mode 100644 index 000000000..5a68396ee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm @@ -0,0 +1,81 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetJump.Asm +; +; Abstract: +; +; Implementation of SetJump() on x64. +; +;------------------------------------------------------------------------------ + +%include "Nasm.inc" + + DEFAULT REL + SECTION .text + +extern ASM_PFX(InternalAssertJumpBuffer) +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; SetJump ( +; OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(SetJump) +ASM_PFX(SetJump): + push rcx + add rsp, -0x20 + call ASM_PFX(InternalAssertJumpBuffer) + add rsp, 0x20 + pop rcx + pop rdx + + xor rax, rax + mov [rcx + 0xF8], rax ; save 0 to SSP + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov rax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov rax, 1 + INCSSP_RAX ; to read original SSP + READSSP_RAX + mov [rcx + 0xF8], rax ; save SSP + +CetDone: + + mov [rcx], rbx + mov [rcx + 8], rsp + mov [rcx + 0x10], rbp + mov [rcx + 0x18], rdi + mov [rcx + 0x20], rsi + mov [rcx + 0x28], r12 + mov [rcx + 0x30], r13 + mov [rcx + 0x38], r14 + mov [rcx + 0x40], r15 + mov [rcx + 0x48], rdx + ; save non-volatile fp registers + stmxcsr [rcx + 0x50] + movdqu [rcx + 0x58], xmm6 + movdqu [rcx + 0x68], xmm7 + movdqu [rcx + 0x78], xmm8 + movdqu [rcx + 0x88], xmm9 + movdqu [rcx + 0x98], xmm10 + movdqu [rcx + 0xA8], xmm11 + movdqu [rcx + 0xB8], xmm12 + movdqu [rcx + 0xC8], xmm13 + movdqu [rcx + 0xD8], xmm14 + movdqu [rcx + 0xE8], xmm15 + xor rax, rax + jmp rdx + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm new file mode 100644 index 000000000..7be666dbd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SwitchStack.Asm +; +; Abstract: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; Routine Description: +; +; Routine for switching stacks with 2 parameters +; +; Arguments: +; +; (rcx) EntryPoint - Entry point with new stack. +; (rdx) Context1 - Parameter1 for entry point. +; (r8) Context2 - Parameter2 for entry point. +; (r9) NewStack - The pointer to new stack. +; +; Returns: +; +; None +; +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSwitchStack) +ASM_PFX(InternalSwitchStack): + mov rax, rcx + mov rcx, rdx + mov rdx, r8 + ; + ; Reserve space for register parameters (rcx, rdx, r8 & r9) on the stack, + ; in case the callee wishes to spill them. + ; + lea rsp, [r9 - 0x20] + call rax + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm new file mode 100644 index 000000000..e83b31c59 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm @@ -0,0 +1,319 @@ + +#include "BaseLibInternals.h" + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Thunk.asm +; +; Abstract: +; +; Real mode thunk +; +;------------------------------------------------------------------------------ + +global ASM_PFX(m16Size) +global ASM_PFX(mThunk16Attr) +global ASM_PFX(m16Gdt) +global ASM_PFX(m16GdtrBase) +global ASM_PFX(mTransition) +global ASM_PFX(m16Start) + +struc IA32_REGS + + ._EDI: resd 1 + ._ESI: resd 1 + ._EBP: resd 1 + ._ESP: resd 1 + ._EBX: resd 1 + ._EDX: resd 1 + ._ECX: resd 1 + ._EAX: resd 1 + ._DS: resw 1 + ._ES: resw 1 + ._FS: resw 1 + ._GS: resw 1 + ._EFLAGS: resq 1 + ._EIP: resd 1 + ._CS: resw 1 + ._SS: resw 1 + .size: + +endstruc + +SECTION .data + +; +; These are global constant to convey information to C code. +; +ASM_PFX(m16Size) DW ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) +ASM_PFX(mThunk16Attr) DW _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start) +ASM_PFX(m16Gdt) DW _NullSeg - ASM_PFX(m16Start) +ASM_PFX(m16GdtrBase) DW _16GdtrBase - ASM_PFX(m16Start) +ASM_PFX(mTransition) DW _EntryPoint - ASM_PFX(m16Start) + +SECTION .text + +ASM_PFX(m16Start): + +SavedGdt: + dw 0 + dq 0 + +;------------------------------------------------------------------------------ +; _BackFromUserCode() takes control in real mode after 'retf' has been executed +; by user code. It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_BackFromUserCode: + ; + ; The order of saved registers on the stack matches the order they appears + ; in IA32_REGS structure. This facilitates wrapper function to extract them + ; into that structure. + ; +BITS 16 + push ss + push cs + ; + ; Note: We can't use o32 on the next instruction because of a bug + ; in NASM 2.09.04 through 2.10rc1. + ; + call dword .Base ; push eip +.Base: + push dword 0 ; reserved high order 32 bits of EFlags + pushfd + cli ; disable interrupts + push gs + push fs + push es + push ds + pushad + mov edx, strict dword 0 +.ThunkAttrEnd: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 + jz .1 + mov ax, 2401h + int 15h + cli ; disable interrupts + jnc .2 +.1: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL + jz .2 + in al, 92h + or al, 2 + out 92h, al ; deactivate A20M# +.2: + xor eax, eax + mov ax, ss + lea ebp, [esp + IA32_REGS.size] + mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp + mov ebx, [bp - IA32_REGS.size + IA32_REGS._EIP] + shl eax, 4 ; shl eax, 4 + add ebp, eax ; add ebp, eax + mov eax, cs + shl eax, 4 + lea eax, [eax + ebx + (.X64JmpEnd - .Base)] + mov [cs:bx + (.X64JmpEnd - 6 - .Base)], eax + mov eax, strict dword 0 +.SavedCr4End: + mov cr4, eax +o32 lgdt [cs:bx + (SavedGdt - .Base)] + mov ecx, 0c0000080h + rdmsr + or ah, 1 + wrmsr + mov eax, strict dword 0 +.SavedCr0End: + mov cr0, eax + jmp 0:strict dword 0 +.X64JmpEnd: +BITS 64 + nop + mov rsp, strict qword 0 +.SavedSpEnd: + nop + ret + +_EntryPoint: + DD _ToUserCode - ASM_PFX(m16Start) + DW CODE16 +_16Gdtr: + DW GDT_SIZE - 1 +_16GdtrBase: + DQ 0 +_16Idtr: + DW (1 << 10) - 1 + DD 0 + +;------------------------------------------------------------------------------ +; _ToUserCode() takes control in real mode before passing control to user code. +; It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_ToUserCode: +BITS 16 + mov ss, dx ; set new segment selectors + mov ds, dx + mov es, dx + mov fs, dx + mov gs, dx + mov ecx, 0c0000080h + mov cr0, eax ; real mode starts at next instruction + rdmsr + and ah, ~1 + wrmsr + mov cr4, ebp + mov ss, si ; set up 16-bit stack segment + mov esp, ebx ; set up 16-bit stack pointer + call dword .Base ; push eip +.Base: + pop ebp ; ebp <- address of .Base + push word [dword esp + IA32_REGS.size + 2] + lea ax, [bp + (.RealMode - .Base)] + push ax + retf ; execution begins at next instruction +.RealMode: + +o32 lidt [cs:bp + (_16Idtr - .Base)] + + popad + pop ds + pop es + pop fs + pop gs + popfd + lea esp, [esp + 4] ; skip high order 32 bits of EFlags + +o32 retf ; transfer control to user code + +ALIGN 8 + +CODE16 equ _16Code - $ +DATA16 equ _16Data - $ +DATA32 equ _32Data - $ + +_NullSeg DQ 0 +_16Code: + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_16Data: + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_32Data: + DW -1 + DW 0 + DB 0 + DB 93h + DB 0cfh ; 16-bit segment, 4GB limit + DB 0 + +GDT_SIZE equ $ - _NullSeg + +;------------------------------------------------------------------------------ +; IA32_REGISTER_SET * +; EFIAPI +; InternalAsmThunk16 ( +; IN IA32_REGISTER_SET *RegisterSet, +; IN OUT VOID *Transition +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalAsmThunk16) +ASM_PFX(InternalAsmThunk16): +BITS 64 + push rbp + push rbx + push rsi + push rdi + + mov ebx, ds + push rbx ; Save ds segment register on the stack + mov ebx, es + push rbx ; Save es segment register on the stack + mov ebx, ss + push rbx ; Save ss segment register on the stack + + push fs + push gs + mov rsi, rcx + movzx r8d, word [rsi + IA32_REGS._SS] + mov edi, [rsi + IA32_REGS._ESP] + lea rdi, [edi - (IA32_REGS.size + 4)] + imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16 + mov ebx, edi ; ebx <- stack for 16-bit code + push IA32_REGS.size / 4 + add edi, eax ; edi <- linear address of 16-bit stack + pop rcx + rep movsd ; copy RegSet + lea ecx, [rdx + (_BackFromUserCode.SavedCr4End - ASM_PFX(m16Start))] + mov eax, edx ; eax <- transition code address + and edx, 0fh + shl eax, 12 ; segment address in high order 16 bits + lea ax, [rdx + (_BackFromUserCode - ASM_PFX(m16Start))] ; offset address + stosd ; [edi] <- return address of user code + + sgdt [rsp + 60h] ; save GDT stack in argument space + movzx r10, word [rsp + 60h] ; r10 <- GDT limit + lea r11, [rcx + (ASM_PFX(InternalAsmThunk16) - _BackFromUserCode.SavedCr4End) + 0xf] + and r11, ~0xf ; r11 <- 16-byte aligned shadowed GDT table in real mode buffer + + mov [rcx + (SavedGdt - _BackFromUserCode.SavedCr4End)], r10w ; save the limit of shadowed GDT table + mov [rcx + (SavedGdt - _BackFromUserCode.SavedCr4End) + 2], r11 ; save the base address of shadowed GDT table + + mov rsi, [rsp + 62h] ; rsi <- the original GDT base address + xchg rcx, r10 ; save rcx to r10 and initialize rcx to be the limit of GDT table + inc rcx ; rcx <- the size of memory to copy + xchg rdi, r11 ; save rdi to r11 and initialize rdi to the base address of shadowed GDT table + rep movsb ; perform memory copy to shadow GDT table + mov rcx, r10 ; restore the orignal rcx before memory copy + mov rdi, r11 ; restore the original rdi before memory copy + + sidt [rsp + 50h] ; save IDT stack in argument space + mov rax, cr0 + mov [rcx + (_BackFromUserCode.SavedCr0End - 4 - _BackFromUserCode.SavedCr4End)], eax + and eax, 7ffffffeh ; clear PE, PG bits + mov rbp, cr4 + mov [rcx - 4], ebp ; save CR4 in _BackFromUserCode.SavedCr4End - 4 + and ebp, ~30h ; clear PAE, PSE bits + mov esi, r8d ; esi <- 16-bit stack segment + push DATA32 + pop rdx ; rdx <- 32-bit data segment selector + lgdt [rcx + (_16Gdtr - _BackFromUserCode.SavedCr4End)] + mov ss, edx + pushfq + lea edx, [rdx + DATA16 - DATA32] + lea r8, [REL .RetFromRealMode] + push r8 + mov r8d, cs + mov [rcx + (_BackFromUserCode.X64JmpEnd - 2 - _BackFromUserCode.SavedCr4End)], r8w + mov [rcx + (_BackFromUserCode.SavedSpEnd - 8 - _BackFromUserCode.SavedCr4End)], rsp + jmp dword far [rcx + (_EntryPoint - _BackFromUserCode.SavedCr4End)] +.RetFromRealMode: + popfq + lgdt [rsp + 60h] ; restore protected mode GDTR + lidt [rsp + 50h] ; restore protected mode IDTR + lea eax, [rbp - IA32_REGS.size] + pop gs + pop fs + pop rbx + mov ss, ebx + pop rbx + mov es, ebx + pop rbx + mov ds, ebx + + pop rdi + pop rsi + pop rbx + pop rbp + + ret diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/VmgExit.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/VmgExit.nasm new file mode 100644 index 000000000..26f034593 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/VmgExit.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; VmgExit.Asm +; +; Abstract: +; +; AsmVmgExit function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmVmgExit ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmVmgExit) +ASM_PFX(AsmVmgExit): + rep vmmcall + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm new file mode 100644 index 000000000..90427fe20 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Wbinvd.Asm +; +; Abstract: +; +; AsmWbinvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWbinvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWbinvd) +ASM_PFX(AsmWbinvd): + wbinvd + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm new file mode 100644 index 000000000..d351396ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr0.Asm +; +; Abstract: +; +; AsmWriteCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr0 ( +; UINTN Cr0 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr0) +ASM_PFX(AsmWriteCr0): + mov cr0, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm new file mode 100644 index 000000000..2b6bce03f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr2.Asm +; +; Abstract: +; +; AsmWriteCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr2 ( +; UINTN Cr2 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr2) +ASM_PFX(AsmWriteCr2): + mov cr2, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm new file mode 100644 index 000000000..fb0b5bad2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr3.Asm +; +; Abstract: +; +; AsmWriteCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr3 ( +; UINTN Cr3 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr3) +ASM_PFX(AsmWriteCr3): + mov cr3, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm new file mode 100644 index 000000000..483a996d8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteCr4.Asm +; +; Abstract: +; +; AsmWriteCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr4 ( +; UINTN Cr4 +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteCr4) +ASM_PFX(AsmWriteCr4): + mov cr4, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm new file mode 100644 index 000000000..3c8815468 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr0.Asm +; +; Abstract: +; +; AsmWriteDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr0 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr0) +ASM_PFX(AsmWriteDr0): + mov dr0, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm new file mode 100644 index 000000000..6fcbbfc9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr1.Asm +; +; Abstract: +; +; AsmWriteDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr1 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr1) +ASM_PFX(AsmWriteDr1): + mov dr1, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm new file mode 100644 index 000000000..a8e0bfc05 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr2.Asm +; +; Abstract: +; +; AsmWriteDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr2 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr2) +ASM_PFX(AsmWriteDr2): + mov dr2, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm new file mode 100644 index 000000000..ac46ab8b7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr3.Asm +; +; Abstract: +; +; AsmWriteDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr3 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr3) +ASM_PFX(AsmWriteDr3): + mov dr3, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm new file mode 100644 index 000000000..c4b12c9e9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr4.Asm +; +; Abstract: +; +; AsmWriteDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr4 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr4) +ASM_PFX(AsmWriteDr4): + ; + ; There's no obvious reason to access this register, since it's aliased to + ; DR6 when DE=0 or an exception generated when DE=1 + ; + DB 0xf, 0x23, 0xe1 + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm new file mode 100644 index 000000000..986a4a95d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr5.Asm +; +; Abstract: +; +; AsmWriteDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr5 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr5) +ASM_PFX(AsmWriteDr5): + ; + ; There's no obvious reason to access this register, since it's aliased to + ; DR7 when DE=0 or an exception generated when DE=1 + ; + DB 0xf, 0x23, 0xe9 + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm new file mode 100644 index 000000000..196993df2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr6.Asm +; +; Abstract: +; +; AsmWriteDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr6 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr6) +ASM_PFX(AsmWriteDr6): + mov dr6, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm new file mode 100644 index 000000000..1b3c18114 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteDr7.Asm +; +; Abstract: +; +; AsmWriteDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr7 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteDr7) +ASM_PFX(AsmWriteDr7): + mov dr7, rcx + mov rax, rcx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm new file mode 100644 index 000000000..0a26ba099 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteGdtr.Asm +; +; Abstract: +; +; AsmWriteGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86WriteGdtr ( +; IN CONST IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86WriteGdtr) +ASM_PFX(InternalX86WriteGdtr): + lgdt [rcx] + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm new file mode 100644 index 000000000..c6155c018 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteIdtr.Asm +; +; Abstract: +; +; AsmWriteIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86WriteIdtr ( +; IN CONST IA32_DESCRIPTOR *Idtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86WriteIdtr) +ASM_PFX(InternalX86WriteIdtr): + pushfq + cli + lidt [rcx] + popfq + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm new file mode 100644 index 000000000..55881db16 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm @@ -0,0 +1,32 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteLdtr.Asm +; +; Abstract: +; +; AsmWriteLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteLdtr ( +; IN UINT16 Ldtr +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteLdtr) +ASM_PFX(AsmWriteLdtr): + lldt cx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm new file mode 100644 index 000000000..3f03529ed --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm0.Asm +; +; Abstract: +; +; AsmWriteMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm0 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm0) +ASM_PFX(AsmWriteMm0): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xc1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm new file mode 100644 index 000000000..f552d4071 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm1.Asm +; +; Abstract: +; +; AsmWriteMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm1 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm1) +ASM_PFX(AsmWriteMm1): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xc9 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm new file mode 100644 index 000000000..1bd176ced --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm2.Asm +; +; Abstract: +; +; AsmWriteMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm2 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm2) +ASM_PFX(AsmWriteMm2): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xd1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm new file mode 100644 index 000000000..403f14073 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm3.Asm +; +; Abstract: +; +; AsmWriteMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm3 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm3) +ASM_PFX(AsmWriteMm3): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xd9 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm new file mode 100644 index 000000000..d99709d49 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm4.Asm +; +; Abstract: +; +; AsmWriteMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm4 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm4) +ASM_PFX(AsmWriteMm4): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xe1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm new file mode 100644 index 000000000..0467ac422 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm5.Asm +; +; Abstract: +; +; AsmWriteMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm5 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm5) +ASM_PFX(AsmWriteMm5): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xe9 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm new file mode 100644 index 000000000..6d2e5eb8f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm6.Asm +; +; Abstract: +; +; AsmWriteMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm6 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm6) +ASM_PFX(AsmWriteMm6): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xf1 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm new file mode 100644 index 000000000..de72adf68 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMm7.Asm +; +; Abstract: +; +; AsmWriteMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteMm7 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMm7) +ASM_PFX(AsmWriteMm7): + ; + ; 64-bit MASM doesn't support MMX instructions, so use opcode here + ; + DB 0x48, 0xf, 0x6e, 0xf9 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c new file mode 100644 index 000000000..98c5458d8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c @@ -0,0 +1,36 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +void __writemsr (unsigned long Register, unsigned __int64 Value); + +#pragma intrinsic(__writemsr) + +/** + Write data to MSR. + + @param Index The register index of MSR. + @param Value Data wants to be written. + + @return Value written to MSR. + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + __writemsr (Index, Value); + return Value; +} + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm new file mode 100644 index 000000000..11224d304 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteMsr64.Asm +; +; Abstract: +; +; AsmWriteMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMsr64 ( +; IN UINT32 Index, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteMsr64) +ASM_PFX(AsmWriteMsr64): + mov rax, rdx ; meanwhile, rax <- return value + shr rdx, 0x20 ; edx:eax contains the value to write + wrmsr + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm new file mode 100644 index 000000000..4e364bc8e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2017, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; WriteTr.nasm +; +; Abstract: +; +; Write TR register +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; AsmWriteTr ( +; UINT16 Selector +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmWriteTr) +ASM_PFX(AsmWriteTr): + mov eax, ecx + ltr ax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X64/XGetBv.nasm b/roms/edk2/MdePkg/Library/BaseLib/X64/XGetBv.nasm new file mode 100644 index 000000000..09f3be8ae --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X64/XGetBv.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; XGetBv.Asm +; +; Abstract: +; +; AsmXgetBv function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmXGetBv ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmXGetBv) +ASM_PFX(AsmXGetBv): + xgetbv + shl rdx, 32 + or rax, rdx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c b/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c new file mode 100644 index 000000000..b7378c028 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c @@ -0,0 +1,60 @@ +/** @file + IA-32/x64 AsmDisablePaging32() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + InternalX86DisablePaging32 (EntryPoint, Context1, Context2, NewStack); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c b/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c new file mode 100644 index 000000000..867a8eba9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c @@ -0,0 +1,57 @@ +/** @file + IA-32/x64 AsmDisablePaging64() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + ASSERT (EntryPoint != 0); + ASSERT (NewStack != 0); + InternalX86DisablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c b/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c new file mode 100644 index 000000000..32a0054d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c @@ -0,0 +1,63 @@ +/** @file + IA-32/x64 AsmEnablePaging32() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + InternalX86EnablePaging32 (EntryPoint, Context1, Context2, NewStack); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c b/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c new file mode 100644 index 000000000..1323e68de --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c @@ -0,0 +1,59 @@ +/** @file + IA-32/x64 AsmEnablePaging64() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + ASSERT (EntryPoint != 0); + ASSERT (NewStack != 0); + InternalX86EnablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86FxRestore.c b/roms/edk2/MdePkg/Library/BaseLib/X86FxRestore.c new file mode 100644 index 000000000..c4fa66856 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86FxRestore.c @@ -0,0 +1,43 @@ +/** @file + IA-32/x64 AsmFxRestore() + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + If Buffer was not saved with AsmFxSave(), then ASSERT(). + + @param Buffer A pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + ASSERT (Buffer != NULL); + ASSERT (0 == ((UINTN)Buffer & 0xf)); + + // + // Check the flag recorded by AsmFxSave() + // + ASSERT (0xAA5555AA == *(UINT32 *) (&Buffer->Buffer[sizeof (Buffer->Buffer) - 4])); + + InternalX86FxRestore (Buffer); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86FxSave.c b/roms/edk2/MdePkg/Library/BaseLib/X86FxSave.c new file mode 100644 index 000000000..2621a08a3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86FxSave.c @@ -0,0 +1,42 @@ +/** @file + IA-32/x64 AsmFxSave() + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param Buffer A pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + ASSERT (Buffer != NULL); + ASSERT (0 == ((UINTN)Buffer & 0xf)); + + InternalX86FxSave (Buffer); + + // + // Mark one flag at end of Buffer, it will be check by AsmFxRestor() + // + *(UINT32 *) (&Buffer->Buffer[sizeof (Buffer->Buffer) - 4]) = 0xAA5555AA; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c b/roms/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c new file mode 100644 index 000000000..4363a7fda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c @@ -0,0 +1,35 @@ +/** @file + IA-32/x64 GetInterruptState() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE is interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + IA32_EFLAGS32 EFlags; + + EFlags.UintN = AsmReadEflags (); + return (BOOLEAN)(1 == EFlags.Bits.IF); +} + + diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c b/roms/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c new file mode 100644 index 000000000..399b36b56 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c @@ -0,0 +1,26 @@ +/** @file + IA-32/x64 MemoryFence(). + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + return; +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86Msr.c b/roms/edk2/MdePkg/Library/BaseLib/X86Msr.c new file mode 100644 index 000000000..ea51ca9ad --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86Msr.c @@ -0,0 +1,654 @@ +/** @file + IA-32/x64 MSR functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + + +/** + Returns the lower 32-bits of a Machine Specific Register(MSR). + + Reads and returns the lower 32-bits of the MSR specified by Index. + No parameter checking is performed on Index, and some Index values may cause + CPU exceptions. The caller must either guarantee that Index is valid, or the + caller must set up exception handlers to catch the exceptions. This function + is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The lower 32 bits of the MSR identified by Index. + +**/ +UINT32 +EFIAPI +AsmReadMsr32 ( + IN UINT32 Index + ) +{ + return (UINT32)AsmReadMsr64 (Index); +} + +/** + Writes a 32-bit value to a Machine Specific Register(MSR), and returns the value. + The upper 32-bits of the MSR are set to zero. + + Writes the 32-bit value specified by Value to the MSR specified by Index. The + upper 32-bits of the MSR write are set to zero. The 32-bit value written to + the MSR is returned. No parameter checking is performed on Index or Value, + and some of these may cause CPU exceptions. The caller must either guarantee + that Index and Value are valid, or the caller must establish proper exception + handlers. This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 32-bit value to write to the MSR. + + @return Value + +**/ +UINT32 +EFIAPI +AsmWriteMsr32 ( + IN UINT32 Index, + IN UINT32 Value + ) +{ + return (UINT32)AsmWriteMsr64 (Index, Value); +} + +/** + Reads a 64-bit MSR, performs a bitwise OR on the lower 32-bits, and + writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the lower 32-bits of the read result and the value specified by + OrData, and writes the result to the 64-bit MSR specified by Index. The lower + 32-bits of the value written to the MSR is returned. No parameter checking is + performed on Index or OrData, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and OrData are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrOr32 ( + IN UINT32 Index, + IN UINT32 OrData + ) +{ + return (UINT32)AsmMsrOr64 (Index, OrData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND on the lower 32-bits, and writes + the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData, and + writes the result to the 64-bit MSR specified by Index. The lower 32-bits of + the value written to the MSR is returned. No parameter checking is performed + on Index or AndData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index and AndData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAnd32 ( + IN UINT32 Index, + IN UINT32 AndData + ) +{ + return (UINT32)AsmMsrAnd64 (Index, AndData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise OR + on the lower 32-bits, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData + preserving the upper 32-bits, performs a bitwise OR between the + result of the AND operation and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Address. The lower 32-bits of the value + written to the MSR is returned. No parameter checking is performed on Index, + AndData, or OrData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index, AndData, and OrData are valid, or the + caller must establish proper exception handlers. This function is only + available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAndThenOr32 ( + IN UINT32 Index, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return (UINT32)AsmMsrAndThenOr64 (Index, AndData, OrData); +} + +/** + Reads a bit field of an MSR. + + Reads the bit field in the lower 32-bits of a 64-bit MSR. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. The caller must either guarantee that Index is valid, or the caller + must set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read from the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldRead32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (AsmReadMsr32 (Index), StartBit, EndBit); +} + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in the lower 32-bits of a 64-bit MSR. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination MSR are preserved. The lower 32-bits of the MSR written is + returned. The caller must either guarantee that Index and the data written + is valid, or the caller must set up exception handlers to catch the exceptions. + This function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldWrite32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT (EndBit < sizeof (Value) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldWrite64 (Index, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The lower 32-bits of the value + written to the MSR are returned. Extra left bits in OrData are stripped. The + caller must either guarantee that Index and the data written is valid, or + the caller must set up exception handlers to catch the exceptions. This + function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (OrData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldOr64 (Index, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The lower 32-bits of the value written to the + MSR are returned. Extra left bits in AndData are stripped. The caller must + either guarantee that Index and the data written is valid, or the caller must + set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAnd32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT (EndBit < sizeof (AndData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldAnd64 (Index, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by a + bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + lower 32-bits of the value written to the MSR are returned. Extra left bits + in both AndData and OrData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAndThenOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (AndData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldAndThenOr64 ( + Index, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 64-bit MSR, performs a bitwise OR, and writes the result + back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. No parameter checking is performed on Index or OrData, and some of + these may cause CPU exceptions. The caller must either guarantee that Index + and OrData are valid, or the caller must establish proper exception handlers. + This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 (Index, AsmReadMsr64 (Index) | OrData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND, and writes the result back to the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by OrData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. No + parameter checking is performed on Index or OrData, and some of these may + cause CPU exceptions. The caller must either guarantee that Index and OrData + are valid, or the caller must establish proper exception handlers. This + function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ) +{ + return AsmWriteMsr64 (Index, AsmReadMsr64 (Index) & AndData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between read + result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit MSR specified by Index. The value written + to the MSR is returned. No parameter checking is performed on Index, AndData, + or OrData, and some of these may cause CPU exceptions. The caller must either + guarantee that Index, AndData, and OrData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 (Index, (AsmReadMsr64 (Index) & AndData) | OrData); +} + +/** + Reads a bit field of an MSR. + + Reads the bit field in the 64-bit MSR. The bit field is specified by the + StartBit and the EndBit. The value of the bit field is returned. The caller + must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read from the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldRead64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (AsmReadMsr64 (Index), StartBit, EndBit); +} + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in a 64-bit MSR. The bit field is specified by + the StartBit and the EndBit. All other bits in the destination MSR are + preserved. The MSR written is returned. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldWrite64 (AsmReadMsr64 (Index), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. Extra left bits in OrData are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldOr64 (AsmReadMsr64 (Index), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. + Extra left bits in AndData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAnd64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldAnd64 (AsmReadMsr64 (Index), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by + a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + value written to the MSR is returned. Extra left bits in both AndData and + OrData are stripped. The caller must either guarantee that Index and the data + written is valid, or the caller must set up exception handlers to catch the + exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAndThenOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldAndThenOr64 ( + AsmReadMsr64 (Index), + StartBit, + EndBit, + AndData, + OrData + ) + ); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c b/roms/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c new file mode 100644 index 000000000..fc70a352d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c @@ -0,0 +1,83 @@ +/** @file + IA-32/x64 PatchInstructionX86() + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ Copyright (C) 2018, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BaseLibInternals.h" + +/** + Patch the immediate operand of an IA32 or X64 instruction such that the byte, + word, dword or qword operand is encoded at the end of the instruction's + binary representation. + + This function should be used to update object code that was compiled with + NASM from assembly source code. Example: + + NASM source code: + + mov eax, strict dword 0 ; the imm32 zero operand will be patched + ASM_PFX(gPatchCr3): + mov cr3, eax + + C source code: + + X86_ASSEMBLY_PATCH_LABEL gPatchCr3; + PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4); + + @param[out] InstructionEnd Pointer right past the instruction to patch. The + immediate operand to patch is expected to + comprise the trailing bytes of the instruction. + If InstructionEnd is closer to address 0 than + ValueSize permits, then ASSERT(). + + @param[in] PatchValue The constant to write to the immediate operand. + The caller is responsible for ensuring that + PatchValue can be represented in the byte, word, + dword or qword operand (as indicated through + ValueSize); otherwise ASSERT(). + + @param[in] ValueSize The size of the operand in bytes; must be 1, 2, + 4, or 8. ASSERT() otherwise. +**/ +VOID +EFIAPI +PatchInstructionX86 ( + OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, + IN UINT64 PatchValue, + IN UINTN ValueSize + ) +{ + // + // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size + // instruction at address 0; forbid it. + // + ASSERT ((UINTN)InstructionEnd > ValueSize); + + switch (ValueSize) { + case 1: + ASSERT (PatchValue <= MAX_UINT8); + *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue; + break; + + case 2: + ASSERT (PatchValue <= MAX_UINT16); + WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue); + break; + + case 4: + ASSERT (PatchValue <= MAX_UINT32); + WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue); + break; + + case 8: + WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue); + break; + + default: + ASSERT (FALSE); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86RdRand.c b/roms/edk2/MdePkg/Library/BaseLib/X86RdRand.c new file mode 100644 index 000000000..dcbd96957 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86RdRand.c @@ -0,0 +1,73 @@ +/** @file + IA-32/x64 AsmRdRandxx() + Generates random number through CPU RdRand instruction. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseLibInternals.h" + +/** + Generates a 16-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + + **/ +BOOLEAN +EFIAPI +AsmRdRand16 ( + OUT UINT16 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand16 (Rand); +} + +/** + Generates a 32-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +AsmRdRand32 ( + OUT UINT32 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand32 (Rand); +} + +/** + Generates a 64-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +AsmRdRand64 ( + OUT UINT64 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand64 (Rand); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c b/roms/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c new file mode 100644 index 000000000..ca7c5de6a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c @@ -0,0 +1,33 @@ +/** @file + IA-32/x64 AsmReadGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (Gdtr != NULL); + InternalX86ReadGdtr (Gdtr); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c b/roms/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c new file mode 100644 index 000000000..f9133f9aa --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c @@ -0,0 +1,33 @@ +/** @file + IA-32/x64 AsmReadIdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (Idtr != NULL); + InternalX86ReadIdtr (Idtr); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c b/roms/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c new file mode 100644 index 000000000..b28fd8de9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c @@ -0,0 +1,30 @@ +/** @file + SpeculationBarrier() function for IA32 and x64. + + Copyright (C) 2018 - 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Uses as a barrier to stop speculative execution. + + Ensures that no later instruction will execute speculatively, until all prior + instructions have completed. + +**/ +VOID +EFIAPI +SpeculationBarrier ( + VOID + ) +{ + if (PcdGet8 (PcdSpeculationBarrierType) == 0x01) { + AsmLfence (); + } else if (PcdGet8 (PcdSpeculationBarrierType) == 0x02) { + AsmCpuid (0x01, NULL, NULL, NULL, NULL); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86Thunk.c b/roms/edk2/MdePkg/Library/BaseLib/X86Thunk.c new file mode 100644 index 000000000..5c8a03989 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86Thunk.c @@ -0,0 +1,262 @@ +/** @file + Real Mode Thunk Functions for IA32 and x64. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "BaseLibInternals.h" + +extern CONST UINT8 m16Start; +extern CONST UINT16 m16Size; +extern CONST UINT16 mThunk16Attr; +extern CONST UINT16 m16Gdt; +extern CONST UINT16 m16GdtrBase; +extern CONST UINT16 mTransition; + +/** + Invokes 16-bit code in big real mode and returns the updated register set. + + This function transfers control to the 16-bit code specified by CS:EIP using + the stack specified by SS:ESP in RegisterSet. The updated registers are saved + on the real mode stack and the starting address of the save area is returned. + + @param RegisterSet Values of registers before invocation of 16-bit code. + @param Transition The pointer to the transition code under 1MB. + + @return The pointer to a IA32_REGISTER_SET structure containing the updated + register values. + +**/ +IA32_REGISTER_SET * +EFIAPI +InternalAsmThunk16 ( + IN IA32_REGISTER_SET *RegisterSet, + IN OUT VOID *Transition + ); + +/** + Retrieves the properties for 16-bit thunk functions. + + Computes the size of the buffer and stack below 1MB required to use the + AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This + buffer size is returned in RealModeBufferSize, and the stack size is returned + in ExtraStackSize. If parameters are passed to the 16-bit real mode code, + then the actual minimum stack size is ExtraStackSize plus the maximum number + of bytes that need to be passed to the 16-bit real mode code. + + If RealModeBufferSize is NULL, then ASSERT(). + If ExtraStackSize is NULL, then ASSERT(). + + @param RealModeBufferSize A pointer to the size of the buffer below 1MB + required to use the 16-bit thunk functions. + @param ExtraStackSize A pointer to the extra size of stack below 1MB + that the 16-bit thunk functions require for + temporary storage in the transition to and from + 16-bit real mode. + +**/ +VOID +EFIAPI +AsmGetThunk16Properties ( + OUT UINT32 *RealModeBufferSize, + OUT UINT32 *ExtraStackSize + ) +{ + ASSERT (RealModeBufferSize != NULL); + ASSERT (ExtraStackSize != NULL); + + *RealModeBufferSize = m16Size; + + // + // Extra 4 bytes for return address, and another 4 bytes for mode transition + // + *ExtraStackSize = sizeof (IA32_DWORD_REGS) + 8; +} + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + IA32_SEGMENT_DESCRIPTOR *RealModeGdt; + + ASSERT (ThunkContext != NULL); + ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000); + ASSERT (ThunkContext->RealModeBufferSize >= m16Size); + ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000); + + CopyMem (ThunkContext->RealModeBuffer, &m16Start, m16Size); + + // + // Point RealModeGdt to the GDT to be used in transition + // + // RealModeGdt[0]: Reserved as NULL descriptor + // RealModeGdt[1]: Code Segment + // RealModeGdt[2]: Data Segment + // RealModeGdt[3]: Call Gate + // + RealModeGdt = (IA32_SEGMENT_DESCRIPTOR*)( + (UINTN)ThunkContext->RealModeBuffer + m16Gdt); + + // + // Update Code & Data Segment Descriptor + // + RealModeGdt[1].Bits.BaseLow = + (UINT32)(UINTN)ThunkContext->RealModeBuffer & ~0xf; + RealModeGdt[1].Bits.BaseMid = + (UINT32)(UINTN)ThunkContext->RealModeBuffer >> 16; + + // + // Update transition code entry point offset + // + *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mTransition) += + (UINT32)(UINTN)ThunkContext->RealModeBuffer & 0xf; + + // + // Update Segment Limits for both Code and Data Segment Descriptors + // + if ((ThunkContext->ThunkAttributes & THUNK_ATTRIBUTE_BIG_REAL_MODE) == 0) { + // + // Set segment limits to 64KB + // + RealModeGdt[1].Bits.LimitHigh = 0; + RealModeGdt[1].Bits.G = 0; + RealModeGdt[2].Bits.LimitHigh = 0; + RealModeGdt[2].Bits.G = 0; + } + + // + // Update GDTBASE for this thunk context + // + *(VOID**)((UINTN)ThunkContext->RealModeBuffer + m16GdtrBase) = RealModeGdt; + + // + // Update Thunk Attributes + // + *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mThunk16Attr) = + ThunkContext->ThunkAttributes; +} + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is used. + This function must be called with interrupts disabled. + + The register state from the RealModeState field of ThunkContext is restored just prior + to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState, + which is used to set the interrupt state when a 16-bit real mode entry point is called. + Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState. + The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to + the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function. + The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction, + so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment + and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry + point must exit with a RETF instruction. The register state is captured into RealModeState immediately + after the RETF instruction is executed. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure + the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode. + This includes the base vectors, the interrupt masks, and the edge/level trigger mode. + + If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code + is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits. + + If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to + disable the A20 mask. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in + ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails, + then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in + ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then ASSERT(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + IA32_REGISTER_SET *UpdatedRegs; + + ASSERT (ThunkContext != NULL); + ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000); + ASSERT (ThunkContext->RealModeBufferSize >= m16Size); + ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000); + ASSERT (((ThunkContext->ThunkAttributes & (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL)) != \ + (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL))); + + UpdatedRegs = InternalAsmThunk16 ( + ThunkContext->RealModeState, + ThunkContext->RealModeBuffer + ); + + CopyMem (ThunkContext->RealModeState, UpdatedRegs, sizeof (*UpdatedRegs)); +} + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + AsmPrepareThunk16 (ThunkContext); + AsmThunk16 (ThunkContext); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86UnitTestHost.c b/roms/edk2/MdePkg/Library/BaseLib/X86UnitTestHost.c new file mode 100644 index 000000000..d0e428457 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86UnitTestHost.c @@ -0,0 +1,2977 @@ +/** @file + IA32/X64 specific Unit Test Host functions. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestHost.h" + +/// +/// Defines for mUnitTestHostBaseLibSegment indexes +/// +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_CS 0 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_DS 1 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_ES 2 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_FS 3 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_GS 4 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_SS 5 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR 6 +#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR 7 + +/// +/// Module global variables for simple system emulation of MSRs, CRx, DRx, +/// GDTR, IDTR, and Segment Selectors. +/// +STATIC UINT64 mUnitTestHostBaseLibMsr[2][0x1000]; +STATIC UINTN mUnitTestHostBaseLibCr[5]; +STATIC UINTN mUnitTestHostBaseLibDr[8]; +STATIC UINT16 mUnitTestHostBaseLibSegment[8]; +STATIC IA32_DESCRIPTOR mUnitTestHostBaseLibGdtr; +STATIC IA32_DESCRIPTOR mUnitTestHostBaseLibIdtr; + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and x64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +UnitTestHostBaseLibAsmCpuid ( + IN UINT32 Index, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ) +{ + if (Eax != NULL) { + *Eax = 0; + } + if (Ebx != NULL) { + *Ebx = 0; + } + if (Ecx != NULL) { + *Ecx = 0; + } + if (Edx != NULL) { + *Edx = 0; + } + return Index; +} + +/** + Retrieves CPUID information using an extended leaf identifier. + + Executes the CPUID instruction with EAX set to the value specified by Index + and ECX set to the value specified by SubIndex. This function always returns + Index. This function is only available on IA-32 and x64. + + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + + @param Index The 32-bit value to load into EAX prior to invoking the + CPUID instruction. + @param SubIndex The 32-bit value to load into ECX prior to invoking the + CPUID instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +UnitTestHostBaseLibAsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ) +{ + if (Eax != NULL) { + *Eax = 0; + } + if (Ebx != NULL) { + *Ebx = 0; + } + if (Ecx != NULL) { + *Ecx = 0; + } + if (Edx != NULL) { + *Edx = 0; + } + return Index; +} + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmDisableCache ( + VOID + ) +{ +} + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmEnableCache ( + VOID + ) +{ +} + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +UnitTestHostBaseLibAsmReadMsr64 ( + IN UINT32 Index + ) +{ + if (Index < 0x1000) { + return mUnitTestHostBaseLibMsr[0][Index]; + } + if (Index >= 0xC0000000 && Index < 0xC0001000) { + return mUnitTestHostBaseLibMsr[1][Index]; + } + return 0; +} + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +UnitTestHostBaseLibAsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + if (Index < 0x1000) { + mUnitTestHostBaseLibMsr[0][Index] = Value; + } + if (Index >= 0xC0000000 && Index < 0xC0001000) { + mUnitTestHostBaseLibMsr[1][Index - 0xC00000000] = Value; + } + return Value; +} + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadCr0 ( + VOID + ) +{ + return mUnitTestHostBaseLibCr[0]; +} + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadCr2 ( + VOID + ) +{ + return mUnitTestHostBaseLibCr[2]; +} + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadCr3 ( + VOID + ) +{ + return mUnitTestHostBaseLibCr[3]; +} + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadCr4 ( + VOID + ) +{ + return mUnitTestHostBaseLibCr[4]; +} + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteCr0 ( + UINTN Cr0 + ) +{ + mUnitTestHostBaseLibCr[0] = Cr0; + return Cr0; +} + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteCr2 ( + UINTN Cr2 + ) +{ + mUnitTestHostBaseLibCr[2] = Cr2; + return Cr2; +} + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteCr3 ( + UINTN Cr3 + ) +{ + mUnitTestHostBaseLibCr[3] = Cr3; + return Cr3; +} + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteCr4 ( + UINTN Cr4 + ) +{ + mUnitTestHostBaseLibCr[4] = Cr4; + return Cr4; +} + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr0 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[0]; +} + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr1 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[1]; +} + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr2 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[2]; +} + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr3 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[3]; +} + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr4 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[4]; +} + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr5 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[5]; +} + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr6 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[6]; +} + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmReadDr7 ( + VOID + ) +{ + return mUnitTestHostBaseLibDr[7]; +} + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr0 ( + UINTN Dr0 + ) +{ + mUnitTestHostBaseLibDr[0] = Dr0; + return Dr0; +} + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr1 ( + UINTN Dr1 + ) +{ + mUnitTestHostBaseLibDr[1] = Dr1; + return Dr1; +} + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr2 ( + UINTN Dr2 + ) +{ + mUnitTestHostBaseLibDr[2] = Dr2; + return Dr2; +} + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr3 ( + UINTN Dr3 + ) +{ + mUnitTestHostBaseLibDr[3] = Dr3; + return Dr3; +} + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr4 ( + UINTN Dr4 + ) +{ + mUnitTestHostBaseLibDr[4] = Dr4; + return Dr4; +} + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr5 ( + UINTN Dr5 + ) +{ + mUnitTestHostBaseLibDr[5] = Dr5; + return Dr5; +} + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr6 ( + UINTN Dr6 + ) +{ + mUnitTestHostBaseLibDr[6] = Dr6; + return Dr6; +} + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmWriteDr7 ( + UINTN Dr7 + ) +{ + mUnitTestHostBaseLibDr[7] = Dr7; + return Dr7; +} + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadCs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_CS]; +} + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadDs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_DS]; +} + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadEs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_ES]; +} + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadFs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_FS]; +} + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadGs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_GS]; +} + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadSs ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_SS]; +} + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadTr ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR]; +} + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + Gdtr = &mUnitTestHostBaseLibGdtr; +} + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + CopyMem (&mUnitTestHostBaseLibGdtr, Gdtr, sizeof (IA32_DESCRIPTOR)); +} + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + Idtr = &mUnitTestHostBaseLibIdtr; +} + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + CopyMem (&mUnitTestHostBaseLibIdtr, Idtr, sizeof (IA32_DESCRIPTOR)); +} + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and x64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +UnitTestHostBaseLibAsmReadLdtr ( + VOID + ) +{ + return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR]; +} + +/** + Writes the current Local Descriptor Table Register (LDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and x64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR] = Ldtr; +} + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and x64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +UnitTestHostBaseLibAsmReadPmc ( + IN UINT32 Index + ) +{ + return 0; +} + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ) +{ + return Eax; +} + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +UnitTestHostBaseLibAsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ) +{ + return Eax; +} + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmWbinvd ( + VOID + ) +{ +} + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmInvd ( + VOID + ) +{ +} + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and x64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress. +**/ +VOID * +EFIAPI +UnitTestHostBaseLibAsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + return LinearAddress; +} + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + EntryPoint (Context1, Context2); +} + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + EntryPoint (Context1, Context2); +} + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + SWITCH_STACK_ENTRY_POINT NewEntryPoint; + + NewEntryPoint = (SWITCH_STACK_ENTRY_POINT)(UINTN)(EntryPoint); + NewEntryPoint ((VOID *)(UINTN)Context1, (VOID *)(UINTN)Context2); +} + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + SWITCH_STACK_ENTRY_POINT NewEntryPoint; + + NewEntryPoint = (SWITCH_STACK_ENTRY_POINT)(UINTN)(EntryPoint); + NewEntryPoint ((VOID *)(UINTN)Context1, (VOID *)(UINTN)Context2); +} + +/** + Retrieves the properties for 16-bit thunk functions. + + Computes the size of the buffer and stack below 1MB required to use the + AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This + buffer size is returned in RealModeBufferSize, and the stack size is returned + in ExtraStackSize. If parameters are passed to the 16-bit real mode code, + then the actual minimum stack size is ExtraStackSize plus the maximum number + of bytes that need to be passed to the 16-bit real mode code. + + If RealModeBufferSize is NULL, then ASSERT(). + If ExtraStackSize is NULL, then ASSERT(). + + @param RealModeBufferSize A pointer to the size of the buffer below 1MB + required to use the 16-bit thunk functions. + @param ExtraStackSize A pointer to the extra size of stack below 1MB + that the 16-bit thunk functions require for + temporary storage in the transition to and from + 16-bit real mode. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmGetThunk16Properties ( + OUT UINT32 *RealModeBufferSize, + OUT UINT32 *ExtraStackSize + ) +{ + *RealModeBufferSize = 0; + *ExtraStackSize = 0; +} + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmPrepareThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ +} + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is used. + This function must be called with interrupts disabled. + + The register state from the RealModeState field of ThunkContext is restored just prior + to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState, + which is used to set the interrupt state when a 16-bit real mode entry point is called. + Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState. + The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to + the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function. + The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction, + so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment + and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry + point must exit with a RETF instruction. The register state is captured into RealModeState immediately + after the RETF instruction is executed. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure + the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode. + This includes the base vectors, the interrupt masks, and the edge/level trigger mode. + + If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code + is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits. + + If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to + disable the A20 mask. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in + ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails, + then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in + ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then ASSERT(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ +} + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ +} + +/** + Load given selector into TR register. + + @param[in] Selector Task segment selector +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmWriteTr ( + IN UINT16 Selector + ) +{ + mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR] = Selector; +} + +/** + Performs a serializing operation on all load-from-memory instructions that + were issued prior the AsmLfence function. + + Executes a LFENCE instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +UnitTestHostBaseLibAsmLfence ( + VOID + ) +{ +} + +/** + Patch the immediate operand of an IA32 or X64 instruction such that the byte, + word, dword or qword operand is encoded at the end of the instruction's + binary representation. + + This function should be used to update object code that was compiled with + NASM from assembly source code. Example: + + NASM source code: + + mov eax, strict dword 0 ; the imm32 zero operand will be patched + ASM_PFX(gPatchCr3): + mov cr3, eax + + C source code: + + X86_ASSEMBLY_PATCH_LABEL gPatchCr3; + PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4); + + @param[out] InstructionEnd Pointer right past the instruction to patch. The + immediate operand to patch is expected to + comprise the trailing bytes of the instruction. + If InstructionEnd is closer to address 0 than + ValueSize permits, then ASSERT(). + + @param[in] PatchValue The constant to write to the immediate operand. + The caller is responsible for ensuring that + PatchValue can be represented in the byte, word, + dword or qword operand (as indicated through + ValueSize); otherwise ASSERT(). + + @param[in] ValueSize The size of the operand in bytes; must be 1, 2, + 4, or 8. ASSERT() otherwise. +**/ +VOID +EFIAPI +UnitTestHostBaseLibPatchInstructionX86 ( + OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, + IN UINT64 PatchValue, + IN UINTN ValueSize + ) +{ +} + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and x64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ) +{ + return gUnitTestHostBaseLib.X86->AsmCpuid (Index, Eax, Ebx, Ecx, Edx); +} + +/** + Retrieves CPUID information using an extended leaf identifier. + + Executes the CPUID instruction with EAX set to the value specified by Index + and ECX set to the value specified by SubIndex. This function always returns + Index. This function is only available on IA-32 and x64. + + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + + @param Index The 32-bit value to load into EAX prior to invoking the + CPUID instruction. + @param SubIndex The 32-bit value to load into ECX prior to invoking the + CPUID instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ) +{ + return gUnitTestHostBaseLib.X86->AsmCpuidEx (Index, SubIndex, Eax, Ebx, Ecx, Edx); +} + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmDisableCache ( + VOID + ) +{ + gUnitTestHostBaseLib.X86->AsmDisableCache (); +} + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmEnableCache ( + VOID + ) +{ + gUnitTestHostBaseLib.X86->AsmEnableCache (); +} + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadMsr64 (Index); +} + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteMsr64 (Index, Value); +} + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadCr0 (); +} + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadCr2 (); +} + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadCr3 (); +} + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadCr4 (); +} + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteCr0 (Cr0); +} + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteCr2 (Cr2); +} + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteCr3 (Cr3); +} + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteCr4 (Cr4); +} + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr0 (); +} + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr1 (); +} + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr2 (); +} + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr3 (); +} + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr4 (); +} + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr5 (); +} + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr6 (); +} + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDr7 (); +} + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr0 (Dr0); +} + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr1 (Dr1); +} + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr2 (Dr2); +} + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr3 (Dr3); +} + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr4 (Dr4); +} + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr5 (Dr5); +} + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr6 (Dr6); +} + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ) +{ + return gUnitTestHostBaseLib.X86->AsmWriteDr7 (Dr7); +} + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadCs (); +} + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadDs (); +} + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadEs (); +} + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadFs (); +} + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadGs (); +} + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadSs (); +} + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadTr (); +} + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + gUnitTestHostBaseLib.X86->AsmReadGdtr (Gdtr); +} + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + gUnitTestHostBaseLib.X86->AsmWriteGdtr (Gdtr); +} + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + gUnitTestHostBaseLib.X86->AsmReadIdtr (Idtr); +} + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + gUnitTestHostBaseLib.X86->AsmWriteIdtr (Idtr); +} + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and x64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadLdtr (); +} + +/** + Writes the current Local Descriptor Table Register (LDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and x64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + gUnitTestHostBaseLib.X86->AsmWriteLdtr (Ldtr); +} + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and x64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ) +{ + return gUnitTestHostBaseLib.X86->AsmReadPmc (Index); +} + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ) +{ + return gUnitTestHostBaseLib.X86->AsmMonitor (Eax, Ecx, Edx); +} + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ) +{ + return gUnitTestHostBaseLib.X86->AsmMwait (Eax, Ecx); +} + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ) +{ + gUnitTestHostBaseLib.X86->AsmWbinvd (); +} + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ) +{ + gUnitTestHostBaseLib.X86->AsmInvd (); +} + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and x64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress. +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + return gUnitTestHostBaseLib.X86->AsmFlushCacheLine (LinearAddress); +} + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + gUnitTestHostBaseLib.X86->AsmEnablePaging32 (EntryPoint, Context1, Context2, NewStack); +} + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + gUnitTestHostBaseLib.X86->AsmDisablePaging32 (EntryPoint, Context1, Context2, NewStack); +} + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + gUnitTestHostBaseLib.X86->AsmEnablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + gUnitTestHostBaseLib.X86->AsmDisablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} + +/** + Retrieves the properties for 16-bit thunk functions. + + Computes the size of the buffer and stack below 1MB required to use the + AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This + buffer size is returned in RealModeBufferSize, and the stack size is returned + in ExtraStackSize. If parameters are passed to the 16-bit real mode code, + then the actual minimum stack size is ExtraStackSize plus the maximum number + of bytes that need to be passed to the 16-bit real mode code. + + If RealModeBufferSize is NULL, then ASSERT(). + If ExtraStackSize is NULL, then ASSERT(). + + @param RealModeBufferSize A pointer to the size of the buffer below 1MB + required to use the 16-bit thunk functions. + @param ExtraStackSize A pointer to the extra size of stack below 1MB + that the 16-bit thunk functions require for + temporary storage in the transition to and from + 16-bit real mode. + +**/ +VOID +EFIAPI +AsmGetThunk16Properties ( + OUT UINT32 *RealModeBufferSize, + OUT UINT32 *ExtraStackSize + ) +{ + gUnitTestHostBaseLib.X86->AsmGetThunk16Properties (RealModeBufferSize, ExtraStackSize); +} + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + gUnitTestHostBaseLib.X86->AsmPrepareThunk16 (ThunkContext); +} + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is used. + This function must be called with interrupts disabled. + + The register state from the RealModeState field of ThunkContext is restored just prior + to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState, + which is used to set the interrupt state when a 16-bit real mode entry point is called. + Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState. + The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to + the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function. + The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction, + so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment + and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry + point must exit with a RETF instruction. The register state is captured into RealModeState immediately + after the RETF instruction is executed. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure + the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode. + This includes the base vectors, the interrupt masks, and the edge/level trigger mode. + + If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code + is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits. + + If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to + disable the A20 mask. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in + ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails, + then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in + ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then ASSERT(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + gUnitTestHostBaseLib.X86->AsmThunk16 (ThunkContext); +} + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + gUnitTestHostBaseLib.X86->AsmPrepareAndThunk16 (ThunkContext); +} + +/** + Load given selector into TR register. + + @param[in] Selector Task segment selector +**/ +VOID +EFIAPI +AsmWriteTr ( + IN UINT16 Selector + ) +{ + gUnitTestHostBaseLib.X86->AsmWriteTr (Selector); +} + +/** + Performs a serializing operation on all load-from-memory instructions that + were issued prior the AsmLfence function. + + Executes a LFENCE instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmLfence ( + VOID + ) +{ + gUnitTestHostBaseLib.X86->AsmLfence (); +} + +/** + Patch the immediate operand of an IA32 or X64 instruction such that the byte, + word, dword or qword operand is encoded at the end of the instruction's + binary representation. + + This function should be used to update object code that was compiled with + NASM from assembly source code. Example: + + NASM source code: + + mov eax, strict dword 0 ; the imm32 zero operand will be patched + ASM_PFX(gPatchCr3): + mov cr3, eax + + C source code: + + X86_ASSEMBLY_PATCH_LABEL gPatchCr3; + PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4); + + @param[out] InstructionEnd Pointer right past the instruction to patch. The + immediate operand to patch is expected to + comprise the trailing bytes of the instruction. + If InstructionEnd is closer to address 0 than + ValueSize permits, then ASSERT(). + + @param[in] PatchValue The constant to write to the immediate operand. + The caller is responsible for ensuring that + PatchValue can be represented in the byte, word, + dword or qword operand (as indicated through + ValueSize); otherwise ASSERT(). + + @param[in] ValueSize The size of the operand in bytes; must be 1, 2, + 4, or 8. ASSERT() otherwise. +**/ +VOID +EFIAPI +PatchInstructionX86 ( + OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, + IN UINT64 PatchValue, + IN UINTN ValueSize + ) +{ + gUnitTestHostBaseLib.X86->PatchInstructionX86 (InstructionEnd, PatchValue, ValueSize); +} + +/// +/// Common services +/// +STATIC UNIT_TEST_HOST_BASE_LIB_COMMON mUnitTestHostBaseLibCommon = { + UnitTestHostBaseLibEnableInterrupts, + UnitTestHostBaseLibDisableInterrupts, + UnitTestHostBaseLibEnableDisableInterrupts, + UnitTestHostBaseLibGetInterruptState, +}; + +/// +/// IA32/X64 services +/// +STATIC UNIT_TEST_HOST_BASE_LIB_X86 mUnitTestHostBaseLibX86 = { + UnitTestHostBaseLibAsmCpuid, + UnitTestHostBaseLibAsmCpuidEx, + UnitTestHostBaseLibAsmDisableCache, + UnitTestHostBaseLibAsmEnableCache, + UnitTestHostBaseLibAsmReadMsr64, + UnitTestHostBaseLibAsmWriteMsr64, + UnitTestHostBaseLibAsmReadCr0, + UnitTestHostBaseLibAsmReadCr2, + UnitTestHostBaseLibAsmReadCr3, + UnitTestHostBaseLibAsmReadCr4, + UnitTestHostBaseLibAsmWriteCr0, + UnitTestHostBaseLibAsmWriteCr2, + UnitTestHostBaseLibAsmWriteCr3, + UnitTestHostBaseLibAsmWriteCr4, + UnitTestHostBaseLibAsmReadDr0, + UnitTestHostBaseLibAsmReadDr1, + UnitTestHostBaseLibAsmReadDr2, + UnitTestHostBaseLibAsmReadDr3, + UnitTestHostBaseLibAsmReadDr4, + UnitTestHostBaseLibAsmReadDr5, + UnitTestHostBaseLibAsmReadDr6, + UnitTestHostBaseLibAsmReadDr7, + UnitTestHostBaseLibAsmWriteDr0, + UnitTestHostBaseLibAsmWriteDr1, + UnitTestHostBaseLibAsmWriteDr2, + UnitTestHostBaseLibAsmWriteDr3, + UnitTestHostBaseLibAsmWriteDr4, + UnitTestHostBaseLibAsmWriteDr5, + UnitTestHostBaseLibAsmWriteDr6, + UnitTestHostBaseLibAsmWriteDr7, + UnitTestHostBaseLibAsmReadCs, + UnitTestHostBaseLibAsmReadDs, + UnitTestHostBaseLibAsmReadEs, + UnitTestHostBaseLibAsmReadFs, + UnitTestHostBaseLibAsmReadGs, + UnitTestHostBaseLibAsmReadSs, + UnitTestHostBaseLibAsmReadTr, + UnitTestHostBaseLibAsmReadGdtr, + UnitTestHostBaseLibAsmWriteGdtr, + UnitTestHostBaseLibAsmReadIdtr, + UnitTestHostBaseLibAsmWriteIdtr, + UnitTestHostBaseLibAsmReadLdtr, + UnitTestHostBaseLibAsmWriteLdtr, + UnitTestHostBaseLibAsmReadPmc, + UnitTestHostBaseLibAsmMonitor, + UnitTestHostBaseLibAsmMwait, + UnitTestHostBaseLibAsmWbinvd, + UnitTestHostBaseLibAsmInvd, + UnitTestHostBaseLibAsmFlushCacheLine, + UnitTestHostBaseLibAsmEnablePaging32, + UnitTestHostBaseLibAsmDisablePaging32, + UnitTestHostBaseLibAsmEnablePaging64, + UnitTestHostBaseLibAsmDisablePaging64, + UnitTestHostBaseLibAsmGetThunk16Properties, + UnitTestHostBaseLibAsmPrepareThunk16, + UnitTestHostBaseLibAsmThunk16, + UnitTestHostBaseLibAsmPrepareAndThunk16, + UnitTestHostBaseLibAsmWriteTr, + UnitTestHostBaseLibAsmLfence, + UnitTestHostBaseLibPatchInstructionX86 +}; + +/// +/// Structure of hook functions for BaseLib functions that can not be used from +/// a host application. A simple emulation of these function is provided by +/// default. A specific unit test can provide its own implementation for any +/// of these functions. +/// +UNIT_TEST_HOST_BASE_LIB gUnitTestHostBaseLib = { + &mUnitTestHostBaseLibCommon, + &mUnitTestHostBaseLibX86 +}; diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c b/roms/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c new file mode 100644 index 000000000..1a570e3d9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c @@ -0,0 +1,33 @@ +/** @file + IA-32/x64 AsmWriteGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (Gdtr != NULL); + InternalX86WriteGdtr (Gdtr); +} diff --git a/roms/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c b/roms/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c new file mode 100644 index 000000000..9ea979b76 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c @@ -0,0 +1,33 @@ +/** @file + IA-32/x64 AsmWriteIdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "BaseLibInternals.h" + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (Idtr != NULL); + InternalX86WriteIdtr (Idtr); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf b/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf new file mode 100644 index 000000000..e84a2c7ee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf @@ -0,0 +1,52 @@ +## @file +# Instance of Base Memory Library without assembly. +# +# Base Memory Library implementation - no ASM. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLib + MODULE_UNI_FILE = BaseMemoryLib.uni + FILE_GUID = fd44e603-002a-4b29-9f5f-529e815b6165 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# + +[Sources] + SetMem.c + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGeneric.c + MemLibGuid.c + CopyMem.c + MemLibInternals.h + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni b/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni new file mode 100644 index 000000000..9e840195b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Base Memory Library without assembly. +// +// Base Memory Library implementation - no ASM. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library without assembly" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library implementation - no ASM." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c new file mode 100644 index 000000000..57d82f08c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer A pointer to the destination buffer to compare. + @param SourceBuffer A pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c new file mode 100644 index 000000000..55e8616c9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c @@ -0,0 +1,148 @@ +/** @file + Implementation of the InternalMemCopyMem routine. This function is broken + out into its own source file so that it can be excluded from a build for a + particular platform easily if an optimized version is desired. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2016, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "MemLibInternals.h" + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer The target of the copy request. + @param SourceBuffer The place to copy from. + @param Length The number of bytes to copy. + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memcpy() + // + volatile UINT8 *Destination8; + CONST UINT8 *Source8; + volatile UINT32 *Destination32; + CONST UINT32 *Source32; + volatile UINT64 *Destination64; + CONST UINT64 *Source64; + UINTN Alignment; + + if ((((UINTN)DestinationBuffer & 0x7) == 0) && (((UINTN)SourceBuffer & 0x7) == 0) && (Length >= 8)) { + if (SourceBuffer > DestinationBuffer) { + Destination64 = (UINT64*)DestinationBuffer; + Source64 = (CONST UINT64*)SourceBuffer; + while (Length >= 8) { + *(Destination64++) = *(Source64++); + Length -= 8; + } + + // Finish if there are still some bytes to copy + Destination8 = (UINT8*)Destination64; + Source8 = (CONST UINT8*)Source64; + while (Length-- != 0) { + *(Destination8++) = *(Source8++); + } + } else if (SourceBuffer < DestinationBuffer) { + Destination64 = (UINT64*)((UINTN)DestinationBuffer + Length); + Source64 = (CONST UINT64*)((UINTN)SourceBuffer + Length); + + // Destination64 and Source64 were aligned on a 64-bit boundary + // but if length is not a multiple of 8 bytes then they won't be + // anymore. + + Alignment = Length & 0x7; + if (Alignment != 0) { + Destination8 = (UINT8*)Destination64; + Source8 = (CONST UINT8*)Source64; + + while (Alignment-- != 0) { + *(--Destination8) = *(--Source8); + --Length; + } + Destination64 = (UINT64*)Destination8; + Source64 = (CONST UINT64*)Source8; + } + + while (Length > 0) { + *(--Destination64) = *(--Source64); + Length -= 8; + } + } + } else if ((((UINTN)DestinationBuffer & 0x3) == 0) && (((UINTN)SourceBuffer & 0x3) == 0) && (Length >= 4)) { + if (SourceBuffer > DestinationBuffer) { + Destination32 = (UINT32*)DestinationBuffer; + Source32 = (CONST UINT32*)SourceBuffer; + while (Length >= 4) { + *(Destination32++) = *(Source32++); + Length -= 4; + } + + // Finish if there are still some bytes to copy + Destination8 = (UINT8*)Destination32; + Source8 = (CONST UINT8*)Source32; + while (Length-- != 0) { + *(Destination8++) = *(Source8++); + } + } else if (SourceBuffer < DestinationBuffer) { + Destination32 = (UINT32*)((UINTN)DestinationBuffer + Length); + Source32 = (CONST UINT32*)((UINTN)SourceBuffer + Length); + + // Destination32 and Source32 were aligned on a 32-bit boundary + // but if length is not a multiple of 4 bytes then they won't be + // anymore. + + Alignment = Length & 0x3; + if (Alignment != 0) { + Destination8 = (UINT8*)Destination32; + Source8 = (CONST UINT8*)Source32; + + while (Alignment-- != 0) { + *(--Destination8) = *(--Source8); + --Length; + } + Destination32 = (UINT32*)Destination8; + Source32 = (CONST UINT32*)Source8; + } + + while (Length > 0) { + *(--Destination32) = *(--Source32); + Length -= 4; + } + } + } else { + if (SourceBuffer > DestinationBuffer) { + Destination8 = (UINT8*)DestinationBuffer; + Source8 = (CONST UINT8*)SourceBuffer; + while (Length-- != 0) { + *(Destination8++) = *(Source8++); + } + } else if (SourceBuffer < DestinationBuffer) { + Destination8 = (UINT8*)DestinationBuffer + (Length - 1); + Source8 = (CONST UINT8*)SourceBuffer + (Length - 1); + while (Length-- != 0) { + *(Destination8--) = *(Source8--); + } + } + } + return DestinationBuffer; +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c new file mode 100644 index 000000000..1ac5f33f2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer A pointer to the destination buffer of the memory copy. + @param SourceBuffer A pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c new file mode 100644 index 000000000..6a261ae34 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c @@ -0,0 +1,287 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT16*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT32*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT64*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Length The number of bytes to set. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + Pointer = (CONST UINT8*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + Pointer = (CONST UINT16*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + Pointer = (CONST UINT32*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + Pointer = (CONST UINT64*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + CONST UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < Length; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c new file mode 100644 index 000000000..e2976dd0c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid A pointer to the destination GUID. + @param SourceGuid A pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h new file mode 100644 index 000000000..9d3730aff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer Target of copy + @param SourceBuffer Place to copy from + @param Length The number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The calue to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 000000000..fb2c5a4e0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer, or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer, or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c new file mode 100644 index 000000000..d42abb128 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c @@ -0,0 +1,81 @@ +/** @file + Implementation of the EfiSetMem routine. This function is broken + out into its own source file so that it can be excluded from a + build for a particular platform easily if an optimized version + is desired. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2016, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "MemLibInternals.h" + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memset() + // + volatile UINT8 *Pointer8; + volatile UINT32 *Pointer32; + volatile UINT64 *Pointer64; + UINT32 Value32; + UINT64 Value64; + + if ((((UINTN)Buffer & 0x7) == 0) && (Length >= 8)) { + // Generate the 64bit value + Value32 = (Value << 24) | (Value << 16) | (Value << 8) | Value; + Value64 = LShiftU64 (Value32, 32) | Value32; + + Pointer64 = (UINT64*)Buffer; + while (Length >= 8) { + *(Pointer64++) = Value64; + Length -= 8; + } + + // Finish with bytes if needed + Pointer8 = (UINT8*)Pointer64; + } else if ((((UINTN)Buffer & 0x3) == 0) && (Length >= 4)) { + // Generate the 32bit value + Value32 = (Value << 24) | (Value << 16) | (Value << 8) | Value; + + Pointer32 = (UINT32*)Buffer; + while (Length >= 4) { + *(Pointer32++) = Value32; + Length -= 4; + } + + // Finish with bytes if needed + Pointer8 = (UINT8*)Pointer32; + } else { + Pointer8 = (UINT8*)Buffer; + } + while (Length-- > 0) { + *(Pointer8++) = Value; + } + return Buffer; +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c new file mode 100644 index 000000000..e504deb9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf new file mode 100644 index 000000000..c470fa442 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf @@ -0,0 +1,102 @@ +## @file +# Instance of Base Memory Library using MMX registers. +# +# Base Memory Library that uses MMX registers for high performance. +# Optimized for use in DXE. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibMmx + MODULE_UNI_FILE = BaseMemoryLibMmx.uni + FILE_GUID = d458a654-f64c-49db-b8d1-3821306bf1f6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + + +[Sources] + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGuid.c + MemLibInternals.h + +[Sources.Ia32] + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/IsZeroBuffer.nasm + +[Sources.X64] + X64/ZeroMem.nasm + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/ZeroMem.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/IsZeroBuffer.nasm + + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni new file mode 100644 index 000000000..798c1b6f9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library using MMX registers. +// +// Base Memory Library that uses MMX registers for high performance. +// Optimized for use in DXE. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library using MMX registers" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library that uses MMX registers for high performance. Optimized for use in DXE." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm new file mode 100644 index 000000000..6d56d48f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push esi + push edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte [esi - 1] + movzx edx, byte [edi - 1] + sub eax, edx + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm new file mode 100644 index 000000000..5cace177d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm @@ -0,0 +1,71 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push esi + push edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [esi + edx - 1] ; eax <- End of Source + cmp esi, edi + jae .0 + cmp eax, edi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +.0: + mov ecx, edx + and edx, 7 + shr ecx, 3 ; ecx <- # of Qwords to copy + jz @CopyBytes + push eax + push eax + movq [esp], mm0 ; save mm0 +.1: + movq mm0, [esi] + movq [edi], mm0 + add esi, 8 + add edi, 8 + loop .1 + movq mm0, [esp] ; restore mm0 + pop ecx ; stack cleanup + pop ecx ; stack cleanup + jmp @CopyBytes +@CopyBackward: + mov esi, eax ; esi <- Last byte in Source + lea edi, [edi + edx - 1] ; edi <- Last byte in Destination + std +@CopyBytes: + mov ecx, edx + rep movsb + cld + mov eax, [esp + 12] + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm new file mode 100644 index 000000000..67288cdff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push edi + mov edi, [esp + 8] ; edi <- Buffer + mov ecx, [esp + 12] ; ecx <- Length + mov edx, ecx ; edx <- ecx + shr ecx, 2 ; ecx <- number of dwords + and edx, 3 ; edx <- number of trailing bytes + xor eax, eax ; eax <- 0, also set ZF + repe scasd + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov ecx, edx + repe scasb + jnz @ReturnFalse + pop edi + mov eax, 1 ; return TRUE + ret +@ReturnFalse: + pop edi + xor eax, eax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm new file mode 100644 index 000000000..7a3332b53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm new file mode 100644 index 000000000..9d602f0f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm new file mode 100644 index 000000000..674bcf03e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + cmp eax, [edi] + lea edi, [edi + 8] + loopne .0 + jne .1 + cmp edx, [edi - 4] + jecxz .1 + jne .0 +.1: + lea eax, [edi - 8] + cmovne eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm new file mode 100644 index 000000000..9244e559b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm new file mode 100644 index 000000000..8af2ea552 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.nasm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push edi + mov al, [esp + 16] + mov ah, al + shrd edx, eax, 16 + shld eax, edx, 16 + mov ecx, [esp + 12] ; ecx <- Count + mov edi, [esp + 8] ; edi <- Buffer + mov edx, ecx + and edx, 7 + shr ecx, 3 ; # of Qwords to set + jz @SetBytes + add esp, -0x10 + movq [esp], mm0 ; save mm0 + movq [esp + 8], mm1 ; save mm1 + movd mm0, eax + movd mm1, eax + psllq mm0, 32 + por mm0, mm1 ; fill mm0 with 8 Value's +.0: + movq [edi], mm0 + add edi, 8 + loop .0 + movq mm0, [esp] ; restore mm0 + movq mm1, [esp + 8] ; restore mm1 + add esp, 0x10 ; stack cleanup +@SetBytes: + mov ecx, edx + rep stosb + mov eax, [esp + 8] ; eax <- Buffer as return value + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm new file mode 100644 index 000000000..065bbe3b9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.nasm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push edi + mov eax, [esp + 16] + shrd edx, eax, 16 + shld eax, edx, 16 + mov edx, [esp + 12] + mov edi, [esp + 8] + mov ecx, edx + and edx, 3 + shr ecx, 2 + jz @SetWords + movd mm0, eax + movd mm1, eax + psllq mm0, 32 + por mm0, mm1 +.0: + movq [edi], mm0 + add edi, 8 + loop .0 +@SetWords: + mov ecx, edx + rep stosw + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm new file mode 100644 index 000000000..3ee7b431e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.nasm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + mov eax, [esp + 4] ; eax <- Buffer as return value + mov ecx, [esp + 8] ; ecx <- Count + movd mm0, dword [esp + 12] ; mm0 <- Value + shr ecx, 1 ; ecx <- number of qwords to set + mov edx, eax ; edx <- Buffer + jz @SetDwords + movq mm1, mm0 + psllq mm1, 32 + por mm0, mm1 +.0: + movq qword [edx], mm0 + lea edx, [edx + 8] ; use "lea" to avoid change in flags + loop .0 +@SetDwords: + jnc .1 + movd dword [edx], mm0 +.1: + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm new file mode 100644 index 000000000..2338cf0ab --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.nasm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + mov eax, [esp + 4] + mov ecx, [esp + 8] + movq mm0, [esp + 12] + mov edx, eax +.0: + movq [edx], mm0 + add edx, 8 + loop .0 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm new file mode 100644 index 000000000..3f5a28e3a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.nasm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push edi + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 3 + jz @ZeroBytes + pxor mm0, mm0 +.0: + movq [edi], mm0 + add edi, 8 + loop .0 +@ZeroBytes: + and edx, 7 + xor eax, eax + mov ecx, edx + rep stosb + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h new file mode 100644 index 000000000..ae3dbaadc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer The target of the copy request. + @param SourceBuffer The place to copy from. + @param Length The number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c new file mode 100644 index 000000000..7b66ccdcb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value Thevalue to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c new file mode 100644 index 000000000..e504deb9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm new file mode 100644 index 000000000..5514ab663 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push rsi + push rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte [rsi - 1] + movzx rdx, byte [rdi - 1] + sub rax, rdx + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm new file mode 100644 index 000000000..5769c00bf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; OUT VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push rsi + push rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rsi + r8 - 1] ; r9 <- End of Source + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae .0 + cmp r9, rdi + jae @CopyBackward ; Copy backward if overlapped +.0: + mov rcx, r8 + and r8, 7 + shr rcx, 3 ; rcx <- # of Qwords to copy + jz @CopyBytes + DB 0x49, 0xf, 0x7e, 0xc2 ; movd r10, mm0 (Save mm0 in r10) +.1: + DB 0xf, 0x6f, 0x6 ; movd mm0, [rsi] + DB 0xf, 0xe7, 0x7 ; movntq [rdi], mm0 + add rsi, 8 + add rdi, 8 + loop .1 + mfence + DB 0x49, 0xf, 0x6e, 0xc2 ; movd mm0, r10 (Restore mm0) + jmp @CopyBytes +@CopyBackward: + mov rsi, r9 ; rsi <- End of Source + lea rdi, [rdi + r8 - 1] ; rdi <- End of Destination + std ; set direction flag +@CopyBytes: + mov rcx, r8 + rep movsb ; Copy bytes backward + cld + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm new file mode 100644 index 000000000..a6e1d817f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push rdi + mov rdi, rcx ; rdi <- Buffer + mov rcx, rdx ; rcx <- Length + shr rcx, 3 ; rcx <- number of qwords + and rdx, 7 ; rdx <- number of trailing bytes + xor rax, rax ; rax <- 0, also set ZF + repe scasq + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov rcx, rdx + repe scasb + jnz @ReturnFalse + pop rdi + mov rax, 1 ; return TRUE + ret +@ReturnFalse: + pop rdi + xor rax, rax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm new file mode 100644 index 000000000..eb385a4a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm new file mode 100644 index 000000000..6fccdf2d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm new file mode 100644 index 000000000..6659aef44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm new file mode 100644 index 000000000..16fd931c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm new file mode 100644 index 000000000..450113ba8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.nasm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; OUT VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push rdi + mov rax, r8 + mov ah, al + DB 0x48, 0xf, 0x6e, 0xc0 ; movd mm0, rax + mov r8, rcx + mov rdi, r8 ; rdi <- Buffer + mov rcx, rdx + and edx, 7 + shr rcx, 3 + jz @SetBytes + DB 0xf, 0x70, 0xC0, 0x0 ; pshufw mm0, mm0, 0h +.0: + DB 0xf, 0xe7, 0x7 ; movntq [rdi], mm0 + add rdi, 8 + loop .0 + mfence +@SetBytes: + mov ecx, edx + rep stosb + mov rax, r8 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm new file mode 100644 index 000000000..4e1f4be2b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.nasm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; OUT VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push rdi + mov rax, r8 + DB 0x48, 0xf, 0x6e, 0xc0 ; movd mm0, rax + mov r8, rcx + mov rdi, r8 + mov rcx, rdx + and edx, 3 + shr rcx, 2 + jz @SetWords + DB 0xf, 0x70, 0xC0, 0x0 ; pshufw mm0, mm0, 0h +.0: + DB 0xf, 0xe7, 0x7 ; movntq [rdi], mm0 + add rdi, 8 + loop .0 + mfence +@SetWords: + mov ecx, edx + rep stosw + mov rax, r8 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm new file mode 100644 index 000000000..b3a738589 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.nasm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + DB 0x49, 0xf, 0x6e, 0xc0 ; movd mm0, r8 (Value) + mov rax, rcx ; rax <- Buffer + xchg rcx, rdx ; rcx <- Count rdx <- Buffer + shr rcx, 1 ; rcx <- # of qwords to set + jz @SetDwords + DB 0xf, 0x70, 0xC0, 0x44 ; pshufw mm0, mm0, 44h +.0: + DB 0xf, 0xe7, 0x2 ; movntq [rdx], mm0 + lea rdx, [rdx + 8] ; use "lea" to avoid flag changes + loop .0 + mfence +@SetDwords: + jnc .1 + DB 0xf, 0x7e, 0x2 ; movd [rdx], mm0 +.1: + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm new file mode 100644 index 000000000..f517e1d23 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.nasm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + DB 0x49, 0xf, 0x6e, 0xc0 ; movd mm0, r8 (Value) + mov rax, rcx ; rax <- Buffer + xchg rcx, rdx ; rcx <- Count +.0: + DB 0xf, 0xe7, 0x2 ; movntq [rdx], mm0 + add rdx, 8 + loop .0 + mfence + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm new file mode 100644 index 000000000..2a85f15b5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.nasm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push rdi + mov rdi, rcx + mov rcx, rdx + mov r8, rdi + and edx, 7 + shr rcx, 3 + jz @ZeroBytes + DB 0xf, 0xef, 0xc0 ; pxor mm0, mm0 +.0: + DB 0xf, 0xe7, 7 ; movntq [rdi], mm0 + add rdi, 8 + loop .0 + DB 0xf, 0xae, 0xf0 ; mfence +@ZeroBytes: + xor eax, eax + mov ecx, edx + rep stosb + mov rax, r8 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S new file mode 100644 index 000000000..b7a566fda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S @@ -0,0 +1,18 @@ +// +// Copyright (c) 2016, Linaro Limited +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + + .text + .align 5 +ASM_GLOBAL ASM_PFX(InternalMemCompareGuid) +ASM_PFX(InternalMemCompareGuid): + mov x2, xzr + ldp x3, x4, [x0] + cbz x1, 0f + ldp x1, x2, [x1] +0: cmp x1, x3 + ccmp x2, x4, #0, eq + cset w0, eq + ret diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S new file mode 100644 index 000000000..ffe4b7a0b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S @@ -0,0 +1,120 @@ +// +// Copyright (c) 2013, Linaro Limited +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Assumptions: +// +// ARMv8-a, AArch64 +// + + +// Parameters and result. +#define src1 x0 +#define src2 x1 +#define limit x2 +#define result x0 + +// Internal variables. +#define data1 x3 +#define data1w w3 +#define data2 x4 +#define data2w w4 +#define diff x6 +#define endloop x7 +#define tmp1 x8 +#define tmp2 x9 +#define pos x11 +#define limit_wd x12 +#define mask x13 + + .p2align 6 +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + eor tmp1, src1, src2 + tst tmp1, #7 + b.ne .Lmisaligned8 + ands tmp1, src1, #7 + b.ne .Lmutual_align + add limit_wd, limit, #7 + lsr limit_wd, limit_wd, #3 + + // Start of performance-critical section -- one 64B cache line. +.Lloop_aligned: + ldr data1, [src1], #8 + ldr data2, [src2], #8 +.Lstart_realigned: + subs limit_wd, limit_wd, #1 + eor diff, data1, data2 // Non-zero if differences found. + csinv endloop, diff, xzr, ne // Last Dword or differences. + cbz endloop, .Lloop_aligned + // End of performance-critical section -- one 64B cache line. + + // Not reached the limit, must have found a diff. + cbnz limit_wd, .Lnot_limit + + // Limit % 8 == 0 => all bytes significant. + ands limit, limit, #7 + b.eq .Lnot_limit + + lsl limit, limit, #3 // Bits -> bytes. + mov mask, #~0 + lsl mask, mask, limit + bic data1, data1, mask + bic data2, data2, mask + + orr diff, diff, mask + +.Lnot_limit: + rev diff, diff + rev data1, data1 + rev data2, data2 + + // The MS-non-zero bit of DIFF marks either the first bit + // that is different, or the end of the significant data. + // Shifting left now will bring the critical information into the + // top bits. + clz pos, diff + lsl data1, data1, pos + lsl data2, data2, pos + + // But we need to zero-extend (char is unsigned) the value and then + // perform a signed 32-bit subtraction. + lsr data1, data1, #56 + sub result, data1, data2, lsr #56 + ret + +.Lmutual_align: + // Sources are mutually aligned, but are not currently at an + // alignment boundary. Round down the addresses and then mask off + // the bytes that precede the start point. + bic src1, src1, #7 + bic src2, src2, #7 + add limit, limit, tmp1 // Adjust the limit for the extra. + lsl tmp1, tmp1, #3 // Bytes beyond alignment -> bits. + ldr data1, [src1], #8 + neg tmp1, tmp1 // Bits to alignment -64. + ldr data2, [src2], #8 + mov tmp2, #~0 + + // Little-endian. Early bytes are at LSB. + lsr tmp2, tmp2, tmp1 // Shift (tmp1 & 63). + add limit_wd, limit, #7 + orr data1, data1, tmp2 + orr data2, data2, tmp2 + lsr limit_wd, limit_wd, #3 + b .Lstart_realigned + + .p2align 6 +.Lmisaligned8: + sub limit, limit, #1 +1: + // Perhaps we can do better than this. + ldrb data1w, [src1], #1 + ldrb data2w, [src2], #1 + subs limit, limit, #1 + ccmp data1w, data2w, #0, cs // NZCV = 0b0000. + b.eq 1b + sub result, data1, data2 + ret diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S new file mode 100644 index 000000000..9fad6d1f2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S @@ -0,0 +1,236 @@ +// +// Copyright (c) 2012 - 2016, Linaro Limited +// All rights reserved. +// Copyright (c) 2015 ARM Ltd +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Assumptions: +// +// ARMv8-a, AArch64, unaligned accesses. +// +// + +#define dstin x0 +#define src x1 +#define count x2 +#define dst x3 +#define srcend x4 +#define dstend x5 +#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define A_hw w7 +#define B_l x8 +#define B_lw w8 +#define B_h x9 +#define C_l x10 +#define C_h x11 +#define D_l x12 +#define D_h x13 +#define E_l x14 +#define E_h x15 +#define F_l srcend +#define F_h dst +#define tmp1 x9 +#define tmp2 x3 + +#define L(l) .L ## l + +// Copies are split into 3 main cases: small copies of up to 16 bytes, +// medium copies of 17..96 bytes which are fully unrolled. Large copies +// of more than 96 bytes align the destination and use an unrolled loop +// processing 64 bytes per iteration. +// Small and medium copies read all data before writing, allowing any +// kind of overlap, and memmove tailcalls memcpy for these cases as +// well as non-overlapping copies. + +__memcpy: + prfm PLDL1KEEP, [src] + add srcend, src, count + add dstend, dstin, count + cmp count, 16 + b.ls L(copy16) + cmp count, 96 + b.hi L(copy_long) + + // Medium copies: 17..96 bytes. + sub tmp1, count, 1 + ldp A_l, A_h, [src] + tbnz tmp1, 6, L(copy96) + ldp D_l, D_h, [srcend, -16] + tbz tmp1, 5, 1f + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [srcend, -32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstend, -32] +1: + stp A_l, A_h, [dstin] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + // Small copies: 0..16 bytes. +L(copy16): + cmp count, 8 + b.lo 1f + ldr A_l, [src] + ldr A_h, [srcend, -8] + str A_l, [dstin] + str A_h, [dstend, -8] + ret + .p2align 4 +1: + tbz count, 2, 1f + ldr A_lw, [src] + ldr A_hw, [srcend, -4] + str A_lw, [dstin] + str A_hw, [dstend, -4] + ret + + // Copy 0..3 bytes. Use a branchless sequence that copies the same + // byte 3 times if count==1, or the 2nd byte twice if count==2. +1: + cbz count, 2f + lsr tmp1, count, 1 + ldrb A_lw, [src] + ldrb A_hw, [srcend, -1] + ldrb B_lw, [src, tmp1] + strb A_lw, [dstin] + strb B_lw, [dstin, tmp1] + strb A_hw, [dstend, -1] +2: ret + + .p2align 4 + // Copy 64..96 bytes. Copy 64 bytes from the start and + // 32 bytes from the end. +L(copy96): + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [src, 32] + ldp D_l, D_h, [src, 48] + ldp E_l, E_h, [srcend, -32] + ldp F_l, F_h, [srcend, -16] + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin, 32] + stp D_l, D_h, [dstin, 48] + stp E_l, E_h, [dstend, -32] + stp F_l, F_h, [dstend, -16] + ret + + // Align DST to 16 byte alignment so that we don't cross cache line + // boundaries on both loads and stores. There are at least 96 bytes + // to copy, so copy 16 bytes unaligned and then align. The loop + // copies 64 bytes per iteration and prefetches one iteration ahead. + + .p2align 4 +L(copy_long): + and tmp1, dstin, 15 + bic dst, dstin, 15 + ldp D_l, D_h, [src] + sub src, src, tmp1 + add count, count, tmp1 // Count is now 16 too large. + ldp A_l, A_h, [src, 16] + stp D_l, D_h, [dstin] + ldp B_l, B_h, [src, 32] + ldp C_l, C_h, [src, 48] + ldp D_l, D_h, [src, 64]! + subs count, count, 128 + 16 // Test and readjust count. + b.ls 2f +1: + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [src, 16] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [src, 32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [src, 48] + stp D_l, D_h, [dst, 64]! + ldp D_l, D_h, [src, 64]! + subs count, count, 64 + b.hi 1b + + // Write the last full set of 64 bytes. The remainder is at most 64 + // bytes, so it is safe to always copy 64 bytes from the end even if + // there is just 1 byte left. +2: + ldp E_l, E_h, [srcend, -64] + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [srcend, -48] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [srcend, -16] + stp D_l, D_h, [dst, 64] + stp E_l, E_h, [dstend, -64] + stp A_l, A_h, [dstend, -48] + stp B_l, B_h, [dstend, -32] + stp C_l, C_h, [dstend, -16] + ret + + +// +// All memmoves up to 96 bytes are done by memcpy as it supports overlaps. +// Larger backwards copies are also handled by memcpy. The only remaining +// case is forward large copies. The destination is aligned, and an +// unrolled loop processes 64 bytes per iteration. +// + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + sub tmp2, dstin, src + cmp count, 96 + ccmp tmp2, count, 2, hi + b.hs __memcpy + + cbz tmp2, 3f + add dstend, dstin, count + add srcend, src, count + + // Align dstend to 16 byte alignment so that we don't cross cache line + // boundaries on both loads and stores. There are at least 96 bytes + // to copy, so copy 16 bytes unaligned and then align. The loop + // copies 64 bytes per iteration and prefetches one iteration ahead. + + and tmp2, dstend, 15 + ldp D_l, D_h, [srcend, -16] + sub srcend, srcend, tmp2 + sub count, count, tmp2 + ldp A_l, A_h, [srcend, -16] + stp D_l, D_h, [dstend, -16] + ldp B_l, B_h, [srcend, -32] + ldp C_l, C_h, [srcend, -48] + ldp D_l, D_h, [srcend, -64]! + sub dstend, dstend, tmp2 + subs count, count, 128 + b.ls 2f + nop +1: + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [srcend, -16] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [srcend, -48] + stp D_l, D_h, [dstend, -64]! + ldp D_l, D_h, [srcend, -64]! + subs count, count, 64 + b.hi 1b + + // Write the last full set of 64 bytes. The remainder is at most 64 + // bytes, so it is safe to always copy 64 bytes from the start even if + // there is just 1 byte left. +2: + ldp E_l, E_h, [src, 48] + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [src, 32] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [src, 16] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [src] + stp D_l, D_h, [dstend, -64] + stp E_l, E_h, [dstin, 48] + stp A_l, A_h, [dstin, 32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin] +3: ret diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S new file mode 100644 index 000000000..8673b76ec --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S @@ -0,0 +1,139 @@ +// +// Copyright (c) 2014, ARM Limited +// All rights Reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Assumptions: +// +// ARMv8-a, AArch64 +// Neon Available. +// + +// Arguments and results. +#define srcin x0 +#define cntin x1 +#define chrin w2 + +#define result x0 + +#define src x3 +#define tmp x4 +#define wtmp2 w5 +#define synd x6 +#define soff x9 +#define cntrem x10 + +#define vrepchr v0 +#define vdata1 v1 +#define vdata2 v2 +#define vhas_chr1 v3 +#define vhas_chr2 v4 +#define vrepmask v5 +#define vend v6 + +// +// Core algorithm: +// +// For each 32-byte chunk we calculate a 64-bit syndrome value, with two bits +// per byte. For each tuple, bit 0 is set if the relevant byte matched the +// requested character and bit 1 is not used (faster than using a 32bit +// syndrome). Since the bits in the syndrome reflect exactly the order in which +// things occur in the original string, counting trailing zeros allows to +// identify exactly which byte has matched. +// + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + // Do not dereference srcin if no bytes to compare. + cbz cntin, .Lzero_length + // + // Magic constant 0x40100401 allows us to identify which lane matches + // the requested byte. + // + mov wtmp2, #0x0401 + movk wtmp2, #0x4010, lsl #16 + dup vrepchr.16b, chrin + // Work with aligned 32-byte chunks + bic src, srcin, #31 + dup vrepmask.4s, wtmp2 + ands soff, srcin, #31 + and cntrem, cntin, #31 + b.eq .Lloop + + // + // Input string is not 32-byte aligned. We calculate the syndrome + // value for the aligned 32 bytes block containing the first bytes + // and mask the irrelevant part. + // + + ld1 {vdata1.16b, vdata2.16b}, [src], #32 + sub tmp, soff, #32 + adds cntin, cntin, tmp + cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b + cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b + and vhas_chr1.16b, vhas_chr1.16b, vrepmask.16b + and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b + addp vend.16b, vhas_chr1.16b, vhas_chr2.16b // 256->128 + addp vend.16b, vend.16b, vend.16b // 128->64 + mov synd, vend.d[0] + // Clear the soff*2 lower bits + lsl tmp, soff, #1 + lsr synd, synd, tmp + lsl synd, synd, tmp + // The first block can also be the last + b.ls .Lmasklast + // Have we found something already? + cbnz synd, .Ltail + +.Lloop: + ld1 {vdata1.16b, vdata2.16b}, [src], #32 + subs cntin, cntin, #32 + cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b + cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b + // If we're out of data we finish regardless of the result + b.ls .Lend + // Use a fast check for the termination condition + orr vend.16b, vhas_chr1.16b, vhas_chr2.16b + addp vend.2d, vend.2d, vend.2d + mov synd, vend.d[0] + // We're not out of data, loop if we haven't found the character + cbz synd, .Lloop + +.Lend: + // Termination condition found, let's calculate the syndrome value + and vhas_chr1.16b, vhas_chr1.16b, vrepmask.16b + and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b + addp vend.16b, vhas_chr1.16b, vhas_chr2.16b // 256->128 + addp vend.16b, vend.16b, vend.16b // 128->64 + mov synd, vend.d[0] + // Only do the clear for the last possible block + b.hi .Ltail + +.Lmasklast: + // Clear the (32 - ((cntrem + soff) % 32)) * 2 upper bits + add tmp, cntrem, soff + and tmp, tmp, #31 + sub tmp, tmp, #32 + neg tmp, tmp, lsl #1 + lsl synd, synd, tmp + lsr synd, synd, tmp + +.Ltail: + // Count the trailing zeros using bit reversing + rbit synd, synd + // Compensate the last post-increment + sub src, src, #32 + // Check that we have found a character + cmp synd, #0 + // And count the leading zeros + clz synd, synd + // Compute the potential result + add result, src, synd, lsr #1 + // Select result or NULL + csel result, xzr, result, eq + ret + +.Lzero_length: + mov result, #0 + ret diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S new file mode 100644 index 000000000..f97484055 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S @@ -0,0 +1,199 @@ +// +// Copyright (c) 2012 - 2016, Linaro Limited +// All rights reserved. +// Copyright (c) 2015 ARM Ltd +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Assumptions: +// +// ARMv8-a, AArch64, unaligned accesses +// +// + +#define dstin x0 +#define count x1 +#define val x2 +#define valw w2 +#define dst x3 +#define dstend x4 +#define tmp1 x5 +#define tmp1w w5 +#define tmp2 x6 +#define tmp2w w6 +#define zva_len x7 +#define zva_lenw w7 + +#define L(l) .L ## l + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + dup v0.8H, valw + lsl count, count, #1 + b 0f + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + dup v0.4S, valw + lsl count, count, #2 + b 0f + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + dup v0.2D, val + lsl count, count, #3 + b 0f + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + movi v0.16B, #0 + b 0f + +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + dup v0.16B, valw +0: add dstend, dstin, count + mov val, v0.D[0] + + cmp count, 96 + b.hi L(set_long) + cmp count, 16 + b.hs L(set_medium) + + // Set 0..15 bytes. + tbz count, 3, 1f + str val, [dstin] + str val, [dstend, -8] + ret + nop +1: tbz count, 2, 2f + str valw, [dstin] + str valw, [dstend, -4] + ret +2: cbz count, 3f + strb valw, [dstin] + tbz count, 1, 3f + strh valw, [dstend, -2] +3: ret + + // Set 17..96 bytes. +L(set_medium): + str q0, [dstin] + tbnz count, 6, L(set96) + str q0, [dstend, -16] + tbz count, 5, 1f + str q0, [dstin, 16] + str q0, [dstend, -32] +1: ret + + .p2align 4 + // Set 64..96 bytes. Write 64 bytes from the start and + // 32 bytes from the end. +L(set96): + str q0, [dstin, 16] + stp q0, q0, [dstin, 32] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 + nop +L(set_long): + bic dst, dstin, 15 + str q0, [dstin] + cmp count, 256 + ccmp val, 0, 0, cs + b.eq L(try_zva) +L(no_zva): + sub count, dstend, dst // Count is 16 too large. + add dst, dst, 16 + sub count, count, 64 + 16 // Adjust count and bias for loop. +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] +L(tail64): + subs count, count, 64 + b.hi 1b +2: stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(try_zva): + mrs tmp1, dczid_el0 + tbnz tmp1w, 4, L(no_zva) + and tmp1w, tmp1w, 15 + cmp tmp1w, 4 // ZVA size is 64 bytes. + b.ne L(zva_128) + + // Write the first and last 64 byte aligned block using stp rather + // than using DC ZVA. This is faster on some cores. +L(zva_64): + str q0, [dst, 16] + stp q0, q0, [dst, 32] + bic dst, dst, 63 + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + sub count, dstend, dst // Count is now 128 too large. + sub count, count, 128+64+64 // Adjust count and bias for loop. + add dst, dst, 128 + nop +1: dc zva, dst + add dst, dst, 64 + subs count, count, 64 + b.hi 1b + stp q0, q0, [dst, 0] + stp q0, q0, [dst, 32] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(zva_128): + cmp tmp1w, 5 // ZVA size is 128 bytes. + b.ne L(zva_other) + + str q0, [dst, 16] + stp q0, q0, [dst, 32] + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + bic dst, dst, 127 + sub count, dstend, dst // Count is now 128 too large. + sub count, count, 128+128 // Adjust count and bias for loop. + add dst, dst, 128 +1: dc zva, dst + add dst, dst, 128 + subs count, count, 128 + b.hi 1b + stp q0, q0, [dstend, -128] + stp q0, q0, [dstend, -96] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + +L(zva_other): + mov tmp2w, 4 + lsl zva_lenw, tmp2w, tmp1w + add tmp1, zva_len, 64 // Max alignment bytes written. + cmp count, tmp1 + blo L(no_zva) + + sub tmp2, zva_len, 1 + add tmp1, dst, zva_len + add dst, dst, 16 + subs count, tmp1, dst // Actual alignment bytes to write. + bic tmp1, tmp1, tmp2 // Aligned dc zva start address. + beq 2f +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] + subs count, count, 64 + b.hi 1b +2: mov dst, tmp1 + sub count, dstend, tmp1 // Remaining bytes to write. + subs count, count, zva_len + b.lo 4f +3: dc zva, dst + add dst, dst, zva_len + subs count, count, zva_len + b.hs 3b +4: add count, count, zva_len + b L(tail64) diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S new file mode 100644 index 000000000..7de70ae34 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S @@ -0,0 +1,44 @@ +// +// Copyright (c) 2016, Linaro Limited +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + + .text + .thumb + .syntax unified + .align 5 + .type ASM_PFX(InternalMemCompareGuid), %function +ASM_GLOBAL ASM_PFX(InternalMemCompareGuid) +ASM_PFX(InternalMemCompareGuid): + push {r4, lr} + ldr r2, [r0] + ldr r3, [r0, #4] + ldr r4, [r0, #8] + ldr r0, [r0, #12] + cbz r1, 1f + ldr ip, [r1] + ldr lr, [r1, #4] + cmp r2, ip + it eq + cmpeq.n r3, lr + beq 0f + movs r0, #0 + pop {r4, pc} + +0: ldr r2, [r1, #8] + ldr r3, [r1, #12] + cmp r4, r2 + it eq + cmpeq.n r0, r3 + bne 2f + movs r0, #1 + pop {r4, pc} + +1: orrs r2, r2, r3 + orrs r4, r4, r0 + movs r0, #1 + orrs r2, r2, r4 +2: it ne + movne.n r0, #0 + pop {r4, pc} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm new file mode 100644 index 000000000..3316b8dc6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm @@ -0,0 +1,48 @@ +; +; Copyright (c) 2016, Linaro Limited +; All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + + EXPORT InternalMemCompareGuid + THUMB + AREA CompareGuid, CODE, READONLY, CODEALIGN, ALIGN=5 + +InternalMemCompareGuid + push {r4, lr} + ldr r2, [r0] + ldr r3, [r0, #4] + ldr r4, [r0, #8] + ldr r0, [r0, #12] + cbz r1, L1 + ldr ip, [r1] + ldr lr, [r1, #4] + cmp r2, ip + it eq + cmpeq r3, lr + beq L0 + movs r0, #0 + pop {r4, pc} + +L0 + ldr r2, [r1, #8] + ldr r3, [r1, #12] + cmp r4, r2 + it eq + cmpeq r0, r3 + bne L2 + movs r0, #1 + pop {r4, pc} + +L1 + orrs r2, r2, r3 + orrs r4, r4, r0 + movs r0, #1 + orrs r2, r2, r4 + +L2 + it ne + movne r0, #0 + pop {r4, pc} + + END diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S new file mode 100644 index 000000000..d32816c7b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S @@ -0,0 +1,117 @@ +// +// Copyright (c) 2013 - 2016, Linaro Limited +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Parameters and result. +#define src1 r0 +#define src2 r1 +#define limit r2 +#define result r0 + +// Internal variables. +#define data1 r3 +#define data2 r4 +#define limit_wd r5 +#define diff r6 +#define tmp1 r7 +#define tmp2 r12 +#define pos r8 +#define mask r14 + + .text + .thumb + .syntax unified + .align 5 + .type ASM_PFX(InternalMemCompareMem), %function +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push {r4-r8, lr} + eor tmp1, src1, src2 + tst tmp1, #3 + bne .Lmisaligned4 + ands tmp1, src1, #3 + bne .Lmutual_align + add limit_wd, limit, #3 + nop.w + lsr limit_wd, limit_wd, #2 + + // Start of performance-critical section -- one 32B cache line. +.Lloop_aligned: + ldr data1, [src1], #4 + ldr data2, [src2], #4 +.Lstart_realigned: + subs limit_wd, limit_wd, #1 + eor diff, data1, data2 // Non-zero if differences found. + cbnz diff, 0f + bne .Lloop_aligned + // End of performance-critical section -- one 32B cache line. + + // Not reached the limit, must have found a diff. +0: cbnz limit_wd, .Lnot_limit + + // Limit % 4 == 0 => all bytes significant. + ands limit, limit, #3 + beq .Lnot_limit + + lsl limit, limit, #3 // Bits -> bytes. + mov mask, #~0 + lsl mask, mask, limit + bic data1, data1, mask + bic data2, data2, mask + + orr diff, diff, mask + +.Lnot_limit: + rev diff, diff + rev data1, data1 + rev data2, data2 + + // The MS-non-zero bit of DIFF marks either the first bit + // that is different, or the end of the significant data. + // Shifting left now will bring the critical information into the + // top bits. + clz pos, diff + lsl data1, data1, pos + lsl data2, data2, pos + + // But we need to zero-extend (char is unsigned) the value and then + // perform a signed 32-bit subtraction. + lsr data1, data1, #28 + sub result, data1, data2, lsr #28 + pop {r4-r8, pc} + +.Lmutual_align: + // Sources are mutually aligned, but are not currently at an + // alignment boundary. Round down the addresses and then mask off + // the bytes that precede the start point. + bic src1, src1, #3 + bic src2, src2, #3 + add limit, limit, tmp1 // Adjust the limit for the extra. + lsl tmp1, tmp1, #3 // Bytes beyond alignment -> bits. + ldr data1, [src1], #4 + rsb tmp1, tmp1, #32 // Bits to alignment -32. + ldr data2, [src2], #4 + mov tmp2, #~0 + + // Little-endian. Early bytes are at LSB. + lsr tmp2, tmp2, tmp1 // Shift (tmp1 & 31). + add limit_wd, limit, #3 + orr data1, data1, tmp2 + orr data2, data2, tmp2 + lsr limit_wd, limit_wd, #2 + b .Lstart_realigned + +.Lmisaligned4: + sub limit, limit, #1 +1: + // Perhaps we can do better than this. + ldrb data1, [src1], #1 + ldrb data2, [src2], #1 + subs limit, limit, #1 + it cs + cmpcs.n data1, data2 + beq 1b + sub result, data1, data2 + pop {r4-r8, pc} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm new file mode 100644 index 000000000..27a1efc8c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm @@ -0,0 +1,118 @@ +; +; Copyright (c) 2013 - 2016, Linaro Limited +; All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + +; Parameters and result. +#define src1 r0 +#define src2 r1 +#define limit r2 +#define result r0 + +; Internal variables. +#define data1 r3 +#define data2 r4 +#define limit_wd r5 +#define diff r6 +#define tmp1 r7 +#define tmp2 r12 +#define pos r8 +#define mask r14 + + EXPORT InternalMemCompareMem + THUMB + AREA CompareMem, CODE, READONLY + +InternalMemCompareMem + push {r4-r8, lr} + eor tmp1, src1, src2 + tst tmp1, #3 + bne Lmisaligned4 + ands tmp1, src1, #3 + bne Lmutual_align + add limit_wd, limit, #3 + nop.w + lsr limit_wd, limit_wd, #2 + + ; Start of performance-critical section -- one 32B cache line. +Lloop_aligned + ldr data1, [src1], #4 + ldr data2, [src2], #4 +Lstart_realigned + subs limit_wd, limit_wd, #1 + eor diff, data1, data2 ; Non-zero if differences found. + cbnz diff, L0 + bne Lloop_aligned + ; End of performance-critical section -- one 32B cache line. + + ; Not reached the limit, must have found a diff. +L0 + cbnz limit_wd, Lnot_limit + + // Limit % 4 == 0 => all bytes significant. + ands limit, limit, #3 + beq Lnot_limit + + lsl limit, limit, #3 // Bits -> bytes. + mov mask, #~0 + lsl mask, mask, limit + bic data1, data1, mask + bic data2, data2, mask + + orr diff, diff, mask + +Lnot_limit + rev diff, diff + rev data1, data1 + rev data2, data2 + + ; The MS-non-zero bit of DIFF marks either the first bit + ; that is different, or the end of the significant data. + ; Shifting left now will bring the critical information into the + ; top bits. + clz pos, diff + lsl data1, data1, pos + lsl data2, data2, pos + + ; But we need to zero-extend (char is unsigned) the value and then + ; perform a signed 32-bit subtraction. + lsr data1, data1, #28 + sub result, data1, data2, lsr #28 + pop {r4-r8, pc} + +Lmutual_align + ; Sources are mutually aligned, but are not currently at an + ; alignment boundary. Round down the addresses and then mask off + ; the bytes that precede the start point. + bic src1, src1, #3 + bic src2, src2, #3 + add limit, limit, tmp1 ; Adjust the limit for the extra. + lsl tmp1, tmp1, #2 ; Bytes beyond alignment -> bits. + ldr data1, [src1], #4 + neg tmp1, tmp1 ; Bits to alignment -32. + ldr data2, [src2], #4 + mov tmp2, #~0 + + ; Little-endian. Early bytes are at LSB. + lsr tmp2, tmp2, tmp1 ; Shift (tmp1 & 31). + add limit_wd, limit, #3 + orr data1, data1, tmp2 + orr data2, data2, tmp2 + lsr limit_wd, limit_wd, #2 + b Lstart_realigned + +Lmisaligned4 + sub limit, limit, #1 +L1 + // Perhaps we can do better than this. + ldrb data1, [src1], #1 + ldrb data2, [src2], #1 + subs limit, limit, #1 + it cs + cmpcs data1, data2 + beq L1 + sub result, data1, data2 + pop {r4-r8, pc} + + END diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S new file mode 100644 index 000000000..c36af196a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S @@ -0,0 +1,170 @@ +#------------------------------------------------------------------------------ +# +# CopyMem() worker for ARM +# +# This file started out as C code that did 64 bit moves if the buffer was +# 32-bit aligned, else it does a byte copy. It also does a byte copy for +# any trailing bytes. It was updated to do 32-byte copies using stm/ldm. +# +# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + + .text + .thumb + .syntax unified + +/** + Copy Length bytes from Source to Destination. Overlap is OK. + + This implementation + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + + +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +**/ + .type ASM_PFX(InternalMemCopyMem), %function +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push {r4-r11, lr} + // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length) + mov r11, r0 + mov r10, r0 + mov r12, r2 + mov r14, r1 + + cmp r11, r1 + // If (dest < source) + bcc memcopy_check_optim_default + + // If (source + length < dest) + rsb r3, r1, r11 + cmp r12, r3 + bcc memcopy_check_optim_default + b memcopy_check_optim_overlap + +memcopy_check_optim_default: + // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1) + tst r0, #0xF + it ne + movne.n r0, #0 + bne memcopy_default + tst r1, #0xF + it ne + movne.n r3, #0 + it eq + moveq.n r3, #1 + cmp r2, #31 + it ls + movls.n r0, #0 + bls memcopy_default + and r0, r3, #1 + b memcopy_default + +memcopy_check_optim_overlap: + // r10 = dest_end, r14 = source_end + add r10, r11, r12 + add r14, r12, r1 + + // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned) + cmp r2, #31 + it ls + movls.n r0, #0 + it hi + movhi.n r0, #1 + tst r10, #0xF + it ne + movne.n r0, #0 + tst r14, #0xF + it ne + movne.n r0, #0 + b memcopy_overlapped + +memcopy_overlapped_non_optim: + // We read 1 byte from the end of the source buffer + sub r3, r14, #1 + sub r12, r12, #1 + ldrb r3, [r3, #0] + sub r2, r10, #1 + cmp r12, #0 + // We write 1 byte at the end of the dest buffer + sub r10, r10, #1 + sub r14, r14, #1 + strb r3, [r2, #0] + bne memcopy_overlapped_non_optim + b memcopy_end + +// r10 = dest_end, r14 = source_end +memcopy_overlapped: + // Are we in the optimized case ? + cmp r0, #0 + beq memcopy_overlapped_non_optim + + // Optimized Overlapped - Read 32 bytes + sub r14, r14, #32 + sub r12, r12, #32 + cmp r12, #31 + ldmia r14, {r2-r9} + + // If length is less than 32 then disable optim + it ls + movls.n r0, #0 + + cmp r12, #0 + + // Optimized Overlapped - Write 32 bytes + sub r10, r10, #32 + stmia r10, {r2-r9} + + // while (length != 0) + bne memcopy_overlapped + b memcopy_end + +memcopy_default_non_optim: + // Byte copy + ldrb r3, [r14], #1 + sub r12, r12, #1 + strb r3, [r10], #1 + +memcopy_default: + cmp r12, #0 + beq memcopy_end + +// r10 = dest, r14 = source +memcopy_default_loop: + cmp r0, #0 + beq memcopy_default_non_optim + + // Optimized memcopy - Read 32 Bytes + sub r12, r12, #32 + cmp r12, #31 + ldmia r14!, {r2-r9} + + // If length is less than 32 then disable optim + it ls + movls.n r0, #0 + + cmp r12, #0 + + // Optimized memcopy - Write 32 Bytes + stmia r10!, {r2-r9} + + // while (length != 0) + bne memcopy_default_loop + +memcopy_end: + mov r0, r11 + pop {r4-r11, pc} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm new file mode 100644 index 000000000..3ebcfd5b4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm @@ -0,0 +1,141 @@ +;------------------------------------------------------------------------------ +; +; CopyMem() worker for ARM +; +; This file started out as C code that did 64 bit moves if the buffer was +; 32-bit aligned, else it does a byte copy. It also does a byte copy for +; any trailing bytes. It was updated to do 32-byte copies using stm/ldm. +; +; Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+; Copyright (c) 2016, Linaro Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT InternalMemCopyMem + AREA SetMem, CODE, READONLY + THUMB + +InternalMemCopyMem + stmfd sp!, {r4-r11, lr} + // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length) + mov r11, r0 + mov r10, r0 + mov r12, r2 + mov r14, r1 + +memcopy_check_overlapped + cmp r11, r1 + // If (dest < source) + bcc memcopy_check_optim_default + + // If (source + length < dest) + rsb r3, r1, r11 + cmp r12, r3 + bcc memcopy_check_optim_default + b memcopy_check_optim_overlap + +memcopy_check_optim_default + // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1) + tst r0, #0xF + movne r0, #0 + bne memcopy_default + tst r1, #0xF + movne r3, #0 + moveq r3, #1 + cmp r2, #31 + movls r0, #0 + andhi r0, r3, #1 + b memcopy_default + +memcopy_check_optim_overlap + // r10 = dest_end, r14 = source_end + add r10, r11, r12 + add r14, r12, r1 + + // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned) + cmp r2, #31 + movls r0, #0 + movhi r0, #1 + tst r10, #0xF + movne r0, #0 + tst r14, #0xF + movne r0, #0 + b memcopy_overlapped + +memcopy_overlapped_non_optim + // We read 1 byte from the end of the source buffer + sub r3, r14, #1 + sub r12, r12, #1 + ldrb r3, [r3, #0] + sub r2, r10, #1 + cmp r12, #0 + // We write 1 byte at the end of the dest buffer + sub r10, r10, #1 + sub r14, r14, #1 + strb r3, [r2, #0] + bne memcopy_overlapped_non_optim + b memcopy_end + +// r10 = dest_end, r14 = source_end +memcopy_overlapped + // Are we in the optimized case ? + cmp r0, #0 + beq memcopy_overlapped_non_optim + + // Optimized Overlapped - Read 32 bytes + sub r14, r14, #32 + sub r12, r12, #32 + cmp r12, #31 + ldmia r14, {r2-r9} + + // If length is less than 32 then disable optim + movls r0, #0 + + cmp r12, #0 + + // Optimized Overlapped - Write 32 bytes + sub r10, r10, #32 + stmia r10, {r2-r9} + + // while (length != 0) + bne memcopy_overlapped + b memcopy_end + +memcopy_default_non_optim + // Byte copy + ldrb r3, [r14], #1 + sub r12, r12, #1 + strb r3, [r10], #1 + +memcopy_default + cmp r12, #0 + beq memcopy_end + +// r10 = dest, r14 = source +memcopy_default_loop + cmp r0, #0 + beq memcopy_default_non_optim + + // Optimized memcopy - Read 32 Bytes + sub r12, r12, #32 + cmp r12, #31 + ldmia r14!, {r2-r9} + + // If length is less than 32 then disable optim + movls r0, #0 + + cmp r12, #0 + + // Optimized memcopy - Write 32 Bytes + stmia r10!, {r2-r9} + + // while (length != 0) + bne memcopy_default_loop + +memcopy_end + mov r0, r11 + ldmfd sp!, {r4-r11, pc} + + END + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c new file mode 100644 index 000000000..f27b95c11 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c @@ -0,0 +1,159 @@ +/** @file + Implementation of GUID functions for ARM and AARCH64 + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2016, Linaro Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Internal function to compare two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +InternalMemCompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ); + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + ASSERT (DestinationGuid != NULL); + ASSERT (SourceGuid != NULL); + + return InternalMemCopyMem (DestinationGuid, SourceGuid, sizeof (GUID)); +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + ASSERT (Guid1 != NULL); + ASSERT (Guid2 != NULL); + + return InternalMemCompareGuid (Guid1, Guid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (InternalMemCompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + ASSERT (Guid != NULL); + + return InternalMemCompareGuid (Guid, NULL); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S new file mode 100644 index 000000000..c0b2dee5d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S @@ -0,0 +1,122 @@ +// Copyright (c) 2010-2011, Linaro Limited +// All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// +// Written by Dave Gilbert +// +// This memchr routine is optimised on a Cortex-A9 and should work on +// all ARMv7 processors. It has a fast past for short sizes, and has +// an optimised path for large data sets; the worst case is finding the +// match early in a large data set. +// + + +// 2011-02-07 david.gilbert@linaro.org +// Extracted from local git a5b438d861 +// 2011-07-14 david.gilbert@linaro.org +// Import endianness fix from local git ea786f1b +// 2011-12-07 david.gilbert@linaro.org +// Removed unneeded cbz from align loop + +// this lets us check a flag in a 00/ff byte easily in either endianness +#define CHARTSTMASK(c) 1<<(c*8) + + .text + .thumb + .syntax unified + + .type ASM_PFX(InternalMemScanMem8), %function +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + // r0 = start of memory to scan + // r1 = length + // r2 = character to look for + // returns r0 = pointer to character or NULL if not found + uxtb r2, r2 // Don't think we can trust the caller to actually pass a char + + cmp r1, #16 // If it's short don't bother with anything clever + blt 20f + + tst r0, #7 // If it's already aligned skip the next bit + beq 10f + + // Work up to an aligned point +5: + ldrb r3, [r0],#1 + subs r1, r1, #1 + cmp r3, r2 + beq 50f // If it matches exit found + tst r0, #7 + bne 5b // If not aligned yet then do next byte + +10: + // At this point, we are aligned, we know we have at least 8 bytes to work with + push {r4-r7} + orr r2, r2, r2, lsl #8 // expand the match word across to all bytes + orr r2, r2, r2, lsl #16 + bic r4, r1, #7 // Number of double words to work with + mvns r7, #0 // all F's + movs r3, #0 + +15: + ldmia r0!, {r5,r6} + subs r4, r4, #8 + eor r5, r5, r2 // Get it so that r5,r6 have 00's where the bytes match the target + eor r6, r6, r2 + uadd8 r5, r5, r7 // Parallel add 0xff - sets the GE bits for anything that wasn't 0 + sel r5, r3, r7 // bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION + uadd8 r6, r6, r7 // Parallel add 0xff - sets the GE bits for anything that wasn't 0 + sel r6, r5, r7 // chained....bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION + cbnz r6, 60f + bne 15b // (Flags from the subs above) If not run out of bytes then go around again + + pop {r4-r7} + and r2, r2, #0xff // Get r2 back to a single character from the expansion above + and r1, r1, #7 // Leave the count remaining as the number after the double words have been done + +20: + cbz r1, 40f // 0 length or hit the end already then not found + +21: // Post aligned section, or just a short call + ldrb r3, [r0], #1 + subs r1, r1, #1 + eor r3, r3, r2 // r3 = 0 if match - doesn't break flags from sub + cbz r3, 50f + bne 21b // on r1 flags + +40: + movs r0, #0 // not found + bx lr + +50: + subs r0, r0, #1 // found + bx lr + +60: // We're here because the fast path found a hit - now we have to track down exactly which word it was + // r0 points to the start of the double word after the one that was tested + // r5 has the 00/ff pattern for the first word, r6 has the chained value + subs r0, r0, #3 + cmp r5, #0 + it eq + moveq.n r5, r6 // the end is in the 2nd word + it ne + subne.n r0, r0, #4 // or 2nd byte of 1st word + + // r0 currently points to the 3rd byte of the word containing the hit + tst r5, #CHARTSTMASK(0) // 1st character + bne 61f + adds r0, r0, #1 + tst r5, #CHARTSTMASK(1) // 2nd character + bne 61f + adds r0, r0 ,#1 + tst r5, #(3 << 15) // 2nd & 3rd character + // If not the 3rd must be the last one + it eq + addeq.n r0, r0, #1 + +61: + pop {r4-r7} + subs r0, r0, #1 + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm new file mode 100644 index 000000000..00f4bff19 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm @@ -0,0 +1,121 @@ +; Copyright (c) 2010-2011, Linaro Limited +; All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + +; +; Written by Dave Gilbert +; +; This memchr routine is optimised on a Cortex-A9 and should work on +; all ARMv7 processors. It has a fast past for short sizes, and has +; an optimised path for large data sets; the worst case is finding the +; match early in a large data set. +; + + +; 2011-02-07 david.gilbert@linaro.org +; Extracted from local git a5b438d861 +; 2011-07-14 david.gilbert@linaro.org +; Import endianness fix from local git ea786f1b +; 2011-12-07 david.gilbert@linaro.org +; Removed unneeded cbz from align loop + +; this lets us check a flag in a 00/ff byte easily in either endianness +#define CHARTSTMASK(c) 1<<(c*8) + + EXPORT InternalMemScanMem8 + AREA ScanMem, CODE, READONLY + THUMB + +InternalMemScanMem8 + ; r0 = start of memory to scan + ; r1 = length + ; r2 = character to look for + ; returns r0 = pointer to character or NULL if not found + uxtb r2, r2 ; Don't think we can trust the caller to actually pass a char + + cmp r1, #16 ; If it's short don't bother with anything clever + blt L20 + + tst r0, #7 ; If it's already aligned skip the next bit + beq L10 + + ; Work up to an aligned point +L5 + ldrb r3, [r0],#1 + subs r1, r1, #1 + cmp r3, r2 + beq L50 ; If it matches exit found + tst r0, #7 + bne L5 ; If not aligned yet then do next byte + +L10 + ; At this point, we are aligned, we know we have at least 8 bytes to work with + push {r4-r7} + orr r2, r2, r2, lsl #8 ; expand the match word across to all bytes + orr r2, r2, r2, lsl #16 + bic r4, r1, #7 ; Number of double words to work with + mvns r7, #0 ; all F's + movs r3, #0 + +L15 + ldmia r0!, {r5,r6} + subs r4, r4, #8 + eor r5, r5, r2 ; Get it so that r5,r6 have 00's where the bytes match the target + eor r6, r6, r2 + uadd8 r5, r5, r7 ; Parallel add 0xff - sets the GE bits for anything that wasn't 0 + sel r5, r3, r7 ; bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION + uadd8 r6, r6, r7 ; Parallel add 0xff - sets the GE bits for anything that wasn't 0 + sel r6, r5, r7 ; chained....bytes are 00 for none-00 bytes, or ff for 00 bytes - NOTE INVERSION + cbnz r6, L60 + bne L15 ; (Flags from the subs above) If not run out of bytes then go around again + + pop {r4-r7} + and r2, r2, #0xff ; Get r2 back to a single character from the expansion above + and r1, r1, #7 ; Leave the count remaining as the number after the double words have been done + +L20 + cbz r1, L40 ; 0 length or hit the end already then not found + +L21 ; Post aligned section, or just a short call + ldrb r3, [r0], #1 + subs r1, r1, #1 + eor r3, r3, r2 ; r3 = 0 if match - doesn't break flags from sub + cbz r3, L50 + bne L21 ; on r1 flags + +L40 + movs r0, #0 ; not found + bx lr + +L50 + subs r0, r0, #1 ; found + bx lr + +L60 ; We're here because the fast path found a hit - now we have to track down exactly which word it was + ; r0 points to the start of the double word after the one that was tested + ; r5 has the 00/ff pattern for the first word, r6 has the chained value + cmp r5, #0 + itte eq + moveq r5, r6 ; the end is in the 2nd word + subeq r0, r0, #3 ; Points to 2nd byte of 2nd word + subne r0, r0, #7 ; or 2nd byte of 1st word + + ; r0 currently points to the 3rd byte of the word containing the hit + tst r5, #CHARTSTMASK(0) ; 1st character + bne L61 + adds r0, r0, #1 + tst r5, #CHARTSTMASK(1) ; 2nd character + ittt eq + addeq r0, r0 ,#1 + tsteq r5, #(3 << 15) ; 2nd & 3rd character + ; If not the 3rd must be the last one + addeq r0, r0, #1 + +L61 + pop {r4-r7} + subs r0, r0, #1 + bx lr + + END + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c new file mode 100644 index 000000000..e0b4f2707 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c @@ -0,0 +1,136 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "../MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + Pointer = (CONST UINT16*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + Pointer = (CONST UINT32*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + Pointer = (CONST UINT64*)Buffer; + do { + if (*Pointer == Value) { + return Pointer; + } + ++Pointer; + } while (--Length != 0); + return NULL; +} + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + CONST UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < Length; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S new file mode 100644 index 000000000..f6797004e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S @@ -0,0 +1,88 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + + .text + .thumb + .syntax unified + .align 5 + .type ASM_PFX(InternalMemSetMem16), %function +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + uxth r2, r2 + lsl r1, r1, #1 + orr r2, r2, r2, lsl #16 + b 0f + + .type ASM_PFX(InternalMemSetMem32), %function +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + lsl r1, r1, #2 + b 0f + + .type ASM_PFX(InternalMemSetMem64), %function +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + lsl r1, r1, #3 + b 1f + + .align 5 + .type ASM_PFX(InternalMemSetMem), %function +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + uxtb r2, r2 + orr r2, r2, r2, lsl #8 + orr r2, r2, r2, lsl #16 + b 0f + + .type ASM_PFX(InternalMemZeroMem), %function +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + movs r2, #0 +0: mov r3, r2 + +1: push {r4, lr} + cmp r1, #16 // fewer than 16 bytes of input? + add r1, r1, r0 // r1 := dst + length + add lr, r0, #16 + blt 2f + bic lr, lr, #15 // align output pointer + + str r2, [r0] // potentially unaligned store of 4 bytes + str r3, [r0, #4] // potentially unaligned store of 4 bytes + str r2, [r0, #8] // potentially unaligned store of 4 bytes + str r3, [r0, #12] // potentially unaligned store of 4 bytes + beq 1f + +0: add lr, lr, #16 // advance the output pointer by 16 bytes + subs r4, r1, lr // past the output? + blt 3f // break out of the loop + strd r2, r3, [lr, #-16] // aligned store of 16 bytes + strd r2, r3, [lr, #-8] + bne 0b // goto beginning of loop +1: pop {r4, pc} + +2: subs r4, r1, lr +3: adds r4, r4, #16 + subs r1, r1, #8 + cmp r4, #4 // between 4 and 15 bytes? + blt 4f + cmp r4, #8 // between 8 and 15 bytes? + sub r4, lr, #16 + str r2, [r4] // overlapping store of 4 + (4 + 4) + 4 bytes + it gt + strgt.n r3, [r4, #4] + it gt + strgt.n r2, [r1] + str r3, [r1, #4] + pop {r4, pc} + +4: cmp r4, #2 // 2 or 3 bytes? + strb r2, [lr, #-16] // store 1 byte + it ge + strhge.n r2, [r1, #6] // store 2 bytes + pop {r4, pc} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm new file mode 100644 index 000000000..9aee8a0cf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm @@ -0,0 +1,90 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Linaro Ltd. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + EXPORT InternalMemZeroMem + EXPORT InternalMemSetMem + EXPORT InternalMemSetMem16 + EXPORT InternalMemSetMem32 + EXPORT InternalMemSetMem64 + + AREA SetMem, CODE, READONLY, CODEALIGN, ALIGN=5 + THUMB + +InternalMemSetMem16 + uxth r2, r2 + lsl r1, r1, #1 + orr r2, r2, r2, lsl #16 + b B0 + +InternalMemSetMem32 + lsl r1, r1, #2 + b B0 + +InternalMemSetMem64 + lsl r1, r1, #3 + b B1 + + ALIGN 32 +InternalMemSetMem + uxtb r2, r2 + orr r2, r2, r2, lsl #8 + orr r2, r2, r2, lsl #16 + b B0 + +InternalMemZeroMem + movs r2, #0 +B0 + mov r3, r2 + +B1 + push {r4, lr} + cmp r1, #16 ; fewer than 16 bytes of input? + add r1, r1, r0 ; r1 := dst + length + add lr, r0, #16 + blt L2 + bic lr, lr, #15 ; align output pointer + + str r2, [r0] ; potentially unaligned store of 4 bytes + str r3, [r0, #4] ; potentially unaligned store of 4 bytes + str r2, [r0, #8] ; potentially unaligned store of 4 bytes + str r3, [r0, #12] ; potentially unaligned store of 4 bytes + beq L1 + +L0 + add lr, lr, #16 ; advance the output pointer by 16 bytes + subs r4, r1, lr ; past the output? + blt L3 ; break out of the loop + strd r2, r3, [lr, #-16] ; aligned store of 16 bytes + strd r2, r3, [lr, #-8] + bne L0 ; goto beginning of loop +L1 + pop {r4, pc} + +L2 + subs r4, r1, lr +L3 + adds r4, r4, #16 + subs r1, r1, #8 + cmp r4, #4 ; between 4 and 15 bytes? + blt L4 + cmp r4, #8 ; between 8 and 15 bytes? + str r2, [lr, #-16] ; overlapping store of 4 + (4 + 4) + 4 bytes + itt gt + strgt r3, [lr, #-12] + strgt r2, [r1] + str r3, [r1, #4] + pop {r4, pc} + +L4 + cmp r4, #2 ; 2 or 3 bytes? + strb r2, [lr, #-16] ; store 1 byte + it ge + strhge r2, [r1, #6] ; store 2 bytes + pop {r4, pc} + + END diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf new file mode 100644 index 000000000..e4e3d532e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf @@ -0,0 +1,125 @@ +## @file +# Instance of Base Memory Library optimized for use in DXE phase. +# +# Base Memory Library that is optimized for use in DXE phase. +# Uses REP, MMX, XMM registers as required for best performance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibOptDxe + MODULE_UNI_FILE = BaseMemoryLibOptDxe.uni + FILE_GUID = 02BD55C2-AB1D-4b75-B0FD-9A63AE09B31D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + MemLibInternals.h + +[Sources.Ia32] + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/IsZeroBuffer.nasm + MemLibGuid.c + +[Sources.X64] + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/IsZeroBuffer.nasm + MemLibGuid.c + +[Defines.ARM, Defines.AARCH64] + # + # The ARM implementations of this library may perform unaligned accesses, and + # may use DC ZVA instructions that are only allowed when the MMU and D-cache + # are on. Since SEC, PEI_CORE and PEIM modules may execute with the MMU off, + # omit them from the supported module types list for this library. + # + LIBRARY_CLASS = BaseMemoryLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION + +[Sources.ARM] + Arm/ScanMem.S |GCC + Arm/SetMem.S |GCC + Arm/CopyMem.S |GCC + Arm/CompareMem.S |GCC + Arm/CompareGuid.S |GCC + + Arm/ScanMem.asm |RVCT + Arm/SetMem.asm |RVCT + Arm/CopyMem.asm |RVCT + Arm/CompareMem.asm |RVCT + Arm/CompareGuid.asm |RVCT + +[Sources.AARCH64] + AArch64/ScanMem.S + AArch64/SetMem.S + AArch64/CopyMem.S + AArch64/CompareMem.S + AArch64/CompareGuid.S + +[Sources.ARM, Sources.AARCH64] + Arm/ScanMemGeneric.c + Arm/MemLibGuid.c + +[Sources] + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni new file mode 100644 index 000000000..070cb042d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library optimized for use in DXE phase. +// +// Base Memory Library that is optimized for use in DXE phase. +// Uses REP, MMX, XMM registers as required for best performance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Base Memory Library for DXE" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library that is optimized for use in DXE phase. Uses REP, MMX, XMM registers as required for best performance." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm new file mode 100644 index 000000000..6d56d48f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push esi + push edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte [esi - 1] + movzx edx, byte [edi - 1] + sub eax, edx + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm new file mode 100644 index 000000000..0aa371a47 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push esi + push edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [esi + edx - 1] ; eax <- End of Source + cmp esi, edi + jae .0 + cmp eax, edi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +.0: + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz .1 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx ; edx <- remaining bytes to copy + rep movsb +.1: + mov ecx, edx + and edx, 15 + shr ecx, 4 ; ecx <- # of DQwords to copy + jz @CopyBytes + add esp, -16 + movdqu [esp], xmm0 ; save xmm0 +.2: + movdqu xmm0, [esi] ; esi may not be 16-bytes aligned + movntdq [edi], xmm0 ; edi should be 16-bytes aligned + add esi, 16 + add edi, 16 + loop .2 + mfence + movdqu xmm0, [esp] ; restore xmm0 + add esp, 16 ; stack cleanup + jmp @CopyBytes +@CopyBackward: + mov esi, eax ; esi <- Last byte in Source + lea edi, [edi + edx - 1] ; edi <- Last byte in Destination + std +@CopyBytes: + mov ecx, edx + rep movsb + cld + mov eax, [esp + 12] ; eax <- Destination as return value + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm new file mode 100644 index 000000000..67288cdff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push edi + mov edi, [esp + 8] ; edi <- Buffer + mov ecx, [esp + 12] ; ecx <- Length + mov edx, ecx ; edx <- ecx + shr ecx, 2 ; ecx <- number of dwords + and edx, 3 ; edx <- number of trailing bytes + xor eax, eax ; eax <- 0, also set ZF + repe scasd + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov ecx, edx + repe scasb + jnz @ReturnFalse + pop edi + mov eax, 1 ; return TRUE + ret +@ReturnFalse: + pop edi + xor eax, eax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm new file mode 100644 index 000000000..7a3332b53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm new file mode 100644 index 000000000..9d602f0f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm new file mode 100644 index 000000000..674bcf03e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + cmp eax, [edi] + lea edi, [edi + 8] + loopne .0 + jne .1 + cmp edx, [edi - 4] + jecxz .1 + jne .0 +.1: + lea eax, [edi - 8] + cmovne eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm new file mode 100644 index 000000000..9244e559b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm new file mode 100644 index 000000000..6200d5ff9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push edi + mov ecx, [esp + 12] + mov al, [esp + 16] + mov ah, al + shrd edx, eax, 16 + shld eax, edx, 16 + mov edx, ecx + mov edi, [esp + 8] + shr ecx, 2 + rep stosd + mov ecx, edx + and ecx, 3 + rep stosb + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm new file mode 100644 index 000000000..a529d103c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosw + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm new file mode 100644 index 000000000..787499a8a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosd + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm new file mode 100644 index 000000000..243cf18de --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + mov [edi + ecx*8 - 8], eax + mov [edi + ecx*8 - 4], edx + loop .0 + mov eax, edi + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm new file mode 100644 index 000000000..2b06a0958 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push edi + xor eax, eax + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 2 + and edx, 3 + push edi + rep stosd + mov ecx, edx + rep stosb + pop eax + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h new file mode 100644 index 000000000..bbd8b63cb --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer The target of the copy request. + @param SourceBuffer The place to copy from. + @param Length The number of bytes to copy. + + @return Destination. + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c new file mode 100644 index 000000000..6df99e22c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c @@ -0,0 +1,94 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value +The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c new file mode 100644 index 000000000..e504deb9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm new file mode 100644 index 000000000..5514ab663 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push rsi + push rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte [rsi - 1] + movzx rdx, byte [rdi - 1] + sub rax, rdx + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm new file mode 100644 index 000000000..33545712b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push rsi + push rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rsi + r8 - 1] ; r9 <- Last byte of Source + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae .0 ; Copy forward if Source > Destination + cmp r9, rdi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +.0: + xor rcx, rcx + sub rcx, rdi ; rcx <- -rdi + and rcx, 15 ; rcx + rsi should be 16 bytes aligned + jz .1 ; skip if rcx == 0 + cmp rcx, r8 + cmova rcx, r8 + sub r8, rcx + rep movsb +.1: + mov rcx, r8 + and r8, 15 + shr rcx, 4 ; rcx <- # of DQwords to copy + jz @CopyBytes + movdqa [rsp + 0x18], xmm0 ; save xmm0 on stack +.2: + movdqu xmm0, [rsi] ; rsi may not be 16-byte aligned + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rsi, 16 + add rdi, 16 + loop .2 + mfence + movdqa xmm0, [rsp + 0x18] ; restore xmm0 + jmp @CopyBytes ; copy remaining bytes +@CopyBackward: + mov rsi, r9 ; rsi <- Last byte of Source + lea rdi, [rdi + r8 - 1] ; rdi <- Last byte of Destination + std +@CopyBytes: + mov rcx, r8 + rep movsb + cld + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm new file mode 100644 index 000000000..a6e1d817f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push rdi + mov rdi, rcx ; rdi <- Buffer + mov rcx, rdx ; rcx <- Length + shr rcx, 3 ; rcx <- number of qwords + and rdx, 7 ; rdx <- number of trailing bytes + xor rax, rax ; rax <- 0, also set ZF + repe scasq + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov rcx, rdx + repe scasb + jnz @ReturnFalse + pop rdi + mov rax, 1 ; return TRUE + ret +@ReturnFalse: + pop rdi + xor rax, rax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm new file mode 100644 index 000000000..eb385a4a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm new file mode 100644 index 000000000..6fccdf2d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm new file mode 100644 index 000000000..6659aef44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm new file mode 100644 index 000000000..16fd931c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm new file mode 100644 index 000000000..3abc668ed --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push rdi + push rbx + push rcx ; push Buffer + mov rax, r8 ; rax = Value + and rax, 0xff ; rax = lower 8 bits of r8, upper 56 bits are 0 + mov ah, al ; ah = al + mov bx, ax ; bx = ax + shl rax, 0x10 ; rax = ax << 16 + mov ax, bx ; ax = bx + mov rbx, rax ; ebx = eax + shl rax, 0x20 ; rax = rax << 32 + or rax, rbx ; eax = ebx + mov rdi, rcx ; rdi = Buffer + mov rcx, rdx ; rcx = Count + shr rcx, 3 ; rcx = rcx / 8 + cld + rep stosq + mov rcx, rdx ; rcx = rdx + and rcx, 7 ; rcx = rcx & 7 + rep stosb + pop rax ; rax = Buffer + pop rbx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm new file mode 100644 index 000000000..bcf15ad38 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push rdi + push rcx + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosw + pop rax + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm new file mode 100644 index 000000000..a1558bb09 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push rdi + push rcx + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosd + pop rax + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm new file mode 100644 index 000000000..0009f5db2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push rdi + push rcx + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosq + pop rax + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm new file mode 100644 index 000000000..d71be6bef --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push rdi + push rcx ; push Buffer + xor rax, rax ; rax = 0 + mov rdi, rcx ; rdi = Buffer + mov rcx, rdx ; rcx = Count + shr rcx, 3 ; rcx = rcx / 8 + and rdx, 7 ; rdx = rdx & 7 + cld + rep stosq + mov rcx, rdx ; rcx = rdx + rep stosb + pop rax ; rax = Buffer + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf new file mode 100644 index 000000000..0bb4b7ce5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf @@ -0,0 +1,103 @@ +## @file +# Instance of Base Memory Library optimized for use in PEI phase. +# +# Base Memory Library that is optimized for use in PEI phase. +# Uses REP, MMX, XMM registers as required for best performance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibOptPei + MODULE_UNI_FILE = BaseMemoryLibOptPei.uni + FILE_GUID = D6F43B1B-0F21-462b-B8B7-A033C3EB4261 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemLibInternals.h + +[Sources.Ia32] + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/IsZeroBuffer.nasm + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGuid.c + +[Sources.X64] + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/IsZeroBuffer.nasm + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGuid.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni new file mode 100644 index 000000000..e645758b0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library optimized for use in PEI phase. +// +// Base Memory Library that is optimized for use in PEI phase. +// Uses REP, MMX, XMM registers as required for best performance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library optimized for use in the PEI phase" + +#string STR_MODULE_DESCRIPTION #language en-US "This is the Base Memory Library that is optimized for use in the PEI phase. It uses REP, MMX, XMM registers, as required for best performance." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm new file mode 100644 index 000000000..6d56d48f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push esi + push edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte [esi - 1] + movzx edx, byte [edi - 1] + sub eax, edx + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm new file mode 100644 index 000000000..b598caa54 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push esi + push edi + mov esi, [esp+16] ; esi <- Source + mov edi, [esp+12] ; edi <- Destination + mov edx, [esp+20] ; edx <- Count + cmp esi, edi + je @CopyDone + cmp edx, 0 + je @CopyDone + lea eax, [esi + edx - 1] ; eax <- End of Source + cmp esi, edi + jae @CopyBytes + cmp eax, edi + jb @CopyBytes ; Copy backward if overlapped + mov esi, eax ; esi <- End of Source + lea edi, [edi + edx - 1] ; edi <- End of Destination + std +@CopyBytes: + mov ecx, edx + rep movsb ; Copy bytes backward + cld +@CopyDone: + mov eax, [esp + 12] ; eax <- Destination as return value + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm new file mode 100644 index 000000000..67288cdff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push edi + mov edi, [esp + 8] ; edi <- Buffer + mov ecx, [esp + 12] ; ecx <- Length + mov edx, ecx ; edx <- ecx + shr ecx, 2 ; ecx <- number of dwords + and edx, 3 ; edx <- number of trailing bytes + xor eax, eax ; eax <- 0, also set ZF + repe scasd + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov ecx, edx + repe scasb + jnz @ReturnFalse + pop edi + mov eax, 1 ; return TRUE + ret +@ReturnFalse: + pop edi + xor eax, eax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm new file mode 100644 index 000000000..7a3332b53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm new file mode 100644 index 000000000..9d602f0f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm new file mode 100644 index 000000000..674bcf03e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + cmp eax, [edi] + lea edi, [edi + 8] + loopne .0 + jne .1 + cmp edx, [edi - 4] + jecxz .1 + jne .0 +.1: + lea eax, [edi - 8] + cmovne eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm new file mode 100644 index 000000000..9244e559b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm new file mode 100644 index 000000000..6200d5ff9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push edi + mov ecx, [esp + 12] + mov al, [esp + 16] + mov ah, al + shrd edx, eax, 16 + shld eax, edx, 16 + mov edx, ecx + mov edi, [esp + 8] + shr ecx, 2 + rep stosd + mov ecx, edx + and ecx, 3 + rep stosb + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm new file mode 100644 index 000000000..a529d103c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosw + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm new file mode 100644 index 000000000..787499a8a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosd + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm new file mode 100644 index 000000000..243cf18de --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + mov [edi + ecx*8 - 8], eax + mov [edi + ecx*8 - 4], edx + loop .0 + mov eax, edi + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm new file mode 100644 index 000000000..2b06a0958 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push edi + xor eax, eax + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 2 + and edx, 3 + push edi + rep stosd + mov ecx, edx + rep stosb + pop eax + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h new file mode 100644 index 000000000..68cd31626 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer The target of the copy request. + @param SourceBuffer The place to copy from. + @param Length The number of bytes to copy. + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c new file mode 100644 index 000000000..fb7073ac9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm new file mode 100644 index 000000000..5514ab663 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push rsi + push rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte [rsi - 1] + movzx rdx, byte [rdi - 1] + sub rax, rdx + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm new file mode 100644 index 000000000..c29dab6cd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push rsi + push rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rsi + r8 - 1] ; r9 <- End of Source + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae .0 + cmp r9, rdi + jae @CopyBackward ; Copy backward if overlapped +.0: + mov rcx, r8 + and r8, 7 + shr rcx, 3 + rep movsq ; Copy as many Qwords as possible + jmp @CopyBytes +@CopyBackward: + mov rsi, r9 ; rsi <- End of Source + lea rdi, [rdi + r8 - 1] ; esi <- End of Destination + std ; set direction flag +@CopyBytes: + mov rcx, r8 + rep movsb ; Copy bytes backward + cld + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm new file mode 100644 index 000000000..a6e1d817f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push rdi + mov rdi, rcx ; rdi <- Buffer + mov rcx, rdx ; rcx <- Length + shr rcx, 3 ; rcx <- number of qwords + and rdx, 7 ; rdx <- number of trailing bytes + xor rax, rax ; rax <- 0, also set ZF + repe scasq + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov rcx, rdx + repe scasb + jnz @ReturnFalse + pop rdi + mov rax, 1 ; return TRUE + ret +@ReturnFalse: + pop rdi + xor rax, rax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm new file mode 100644 index 000000000..eb385a4a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm new file mode 100644 index 000000000..6fccdf2d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm new file mode 100644 index 000000000..6659aef44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm new file mode 100644 index 000000000..16fd931c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm new file mode 100644 index 000000000..ecf733f8f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push rdi + push rcx ; push Buffer + mov rax, r8 ; rax = Value + mov rdi, rcx ; rdi = Buffer + mov rcx, rdx ; rcx = Count + rep stosb + pop rax ; rax = Buffer + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm new file mode 100644 index 000000000..6d3c59b09 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosw + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm new file mode 100644 index 000000000..fe0dcbebe --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosd + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm new file mode 100644 index 000000000..03228e02c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosq + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm new file mode 100644 index 000000000..b0e6d1d66 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push rdi + push rcx + xor rax, rax + mov rdi, rcx + mov rcx, rdx + shr rcx, 3 + and rdx, 7 + rep stosq + mov ecx, edx + rep stosb + pop rax + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf new file mode 100644 index 000000000..9d4f8769c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf @@ -0,0 +1,100 @@ +## @file +# Instance of Base Memory Library using REP string instructions. +# +# Base Memory Library that uses REP string instructions for +# high performance and small size. Optimized for use in PEI. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibRepStr + MODULE_UNI_FILE = BaseMemoryLibRepStr.uni + FILE_GUID = e7884bf4-51a1-485b-982a-ff89129983bc + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemLibInternals.h + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGuid.c + +[Sources.Ia32] + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/IsZeroBuffer.nasm + +[Sources.X64] + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/IsZeroBuffer.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni new file mode 100644 index 000000000..a41cf830d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library using REP string instructions. +// +// Base Memory Library that uses REP string instructions for +// high performance and small size. Optimized for use in PEI. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library using REP string instructions" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library that uses REP string instructions for high performance and small size. Optimized for use in PEI." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm new file mode 100644 index 000000000..6d56d48f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push esi + push edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte [esi - 1] + movzx edx, byte [edi - 1] + sub eax, edx + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm new file mode 100644 index 000000000..8203ffeb1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push esi + push edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [esi + edx - 1] ; eax <- End of Source + cmp esi, edi + jae .0 + cmp eax, edi + jae @CopyBackward ; Copy backward if overlapped +.0: + mov ecx, edx + and edx, 3 + shr ecx, 2 + rep movsd ; Copy as many Dwords as possible + jmp @CopyBytes +@CopyBackward: + mov esi, eax ; esi <- End of Source + lea edi, [edi + edx - 1] ; edi <- End of Destination + std +@CopyBytes: + mov ecx, edx + rep movsb ; Copy bytes backward + cld + mov eax, [esp + 12] ; eax <- Destination as return value + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm new file mode 100644 index 000000000..67288cdff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push edi + mov edi, [esp + 8] ; edi <- Buffer + mov ecx, [esp + 12] ; ecx <- Length + mov edx, ecx ; edx <- ecx + shr ecx, 2 ; ecx <- number of dwords + and edx, 3 ; edx <- number of trailing bytes + xor eax, eax ; eax <- 0, also set ZF + repe scasd + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov ecx, edx + repe scasb + jnz @ReturnFalse + pop edi + mov eax, 1 ; return TRUE + ret +@ReturnFalse: + pop edi + xor eax, eax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm new file mode 100644 index 000000000..3432b5e4c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + jz .0 + mov eax, ecx +.0: + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm new file mode 100644 index 000000000..fcfdda129 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + jz .0 + mov eax, ecx +.0: + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm new file mode 100644 index 000000000..b220645e1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + cmp eax, [edi] + lea edi, [edi + 8] + loopne .0 + jne .1 + cmp edx, [edi - 4] + jecxz .1 + jne .0 +.1: + lea eax, [edi - 8] + jz .2 + mov eax, ecx +.2: + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm new file mode 100644 index 000000000..cd01de3c6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + jz .0 + mov eax, ecx +.0: + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm new file mode 100644 index 000000000..ec38f70b2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosb + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm new file mode 100644 index 000000000..a529d103c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosw + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm new file mode 100644 index 000000000..787499a8a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosd + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm new file mode 100644 index 000000000..243cf18de --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + mov [edi + ecx*8 - 8], eax + mov [edi + ecx*8 - 4], edx + loop .0 + mov eax, edi + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm new file mode 100644 index 000000000..2b06a0958 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push edi + xor eax, eax + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 2 + and edx, 3 + push edi + rep stosd + mov ecx, edx + rep stosb + pop eax + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h new file mode 100644 index 000000000..5be42bcb8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer Target of copy + @param SourceBuffer Place to copy from + @param Length The number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c new file mode 100644 index 000000000..e504deb9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm new file mode 100644 index 000000000..5514ab663 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push rsi + push rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte [rsi - 1] + movzx rdx, byte [rdi - 1] + sub rax, rdx + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm new file mode 100644 index 000000000..c29dab6cd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push rsi + push rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rsi + r8 - 1] ; r9 <- End of Source + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae .0 + cmp r9, rdi + jae @CopyBackward ; Copy backward if overlapped +.0: + mov rcx, r8 + and r8, 7 + shr rcx, 3 + rep movsq ; Copy as many Qwords as possible + jmp @CopyBytes +@CopyBackward: + mov rsi, r9 ; rsi <- End of Source + lea rdi, [rdi + r8 - 1] ; esi <- End of Destination + std ; set direction flag +@CopyBytes: + mov rcx, r8 + rep movsb ; Copy bytes backward + cld + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm new file mode 100644 index 000000000..a6e1d817f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push rdi + mov rdi, rcx ; rdi <- Buffer + mov rcx, rdx ; rcx <- Length + shr rcx, 3 ; rcx <- number of qwords + and rdx, 7 ; rdx <- number of trailing bytes + xor rax, rax ; rax <- 0, also set ZF + repe scasq + jnz @ReturnFalse ; ZF=0 means non-zero element found + mov rcx, rdx + repe scasb + jnz @ReturnFalse + pop rdi + mov rax, 1 ; return TRUE + ret +@ReturnFalse: + pop rdi + xor rax, rax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm new file mode 100644 index 000000000..eb385a4a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm new file mode 100644 index 000000000..6fccdf2d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm new file mode 100644 index 000000000..6659aef44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm new file mode 100644 index 000000000..16fd931c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm new file mode 100644 index 000000000..d5eaf7a91 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push rdi + mov rax, r8 ; rax = Value + mov rdi, rcx ; rdi = Buffer + xchg rcx, rdx ; rcx = Count, rdx = Buffer + rep stosb + mov rax, rdx ; rax = Buffer + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm new file mode 100644 index 000000000..6d3c59b09 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosw + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm new file mode 100644 index 000000000..fe0dcbebe --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosd + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm new file mode 100644 index 000000000..03228e02c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + push rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosq + mov rax, rdx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm new file mode 100644 index 000000000..b0e6d1d66 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push rdi + push rcx + xor rax, rax + mov rdi, rcx + mov rcx, rdx + shr rcx, 3 + and rdx, 7 + rep stosq + mov ecx, edx + rep stosb + pop rax + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf new file mode 100644 index 000000000..79618c9fd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf @@ -0,0 +1,99 @@ +## @file +# Instance of Base Memory Library using SSE2 registers. +# +# Base Memory Library that uses SSE2 registers for high performance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibSse2 + MODULE_UNI_FILE = BaseMemoryLibSse2.uni + FILE_GUID = 65a18235-5096-4032-8c63-214f0249ce8d + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemLibInternals.h + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGuid.c + +[Sources.Ia32] + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/ScanMem64.nasm + Ia32/ScanMem32.nasm + Ia32/ScanMem16.nasm + Ia32/ScanMem8.nasm + Ia32/CompareMem.nasm + Ia32/ZeroMem.nasm + Ia32/SetMem64.nasm + Ia32/SetMem32.nasm + Ia32/SetMem16.nasm + Ia32/SetMem.nasm + Ia32/CopyMem.nasm + Ia32/IsZeroBuffer.nasm + +[Sources.X64] + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/ScanMem64.nasm + X64/ScanMem32.nasm + X64/ScanMem16.nasm + X64/ScanMem8.nasm + X64/CompareMem.nasm + X64/ZeroMem.nasm + X64/SetMem64.nasm + X64/SetMem32.nasm + X64/SetMem16.nasm + X64/SetMem.nasm + X64/CopyMem.nasm + X64/IsZeroBuffer.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni new file mode 100644 index 000000000..59c67f973 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Base Memory Library using SSE2 registers. +// +// Base Memory Library that uses SSE2 registers for high performance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library using SSE2 registers" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library that uses SSE2 registers for high performance." + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm new file mode 100644 index 000000000..6d56d48f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push esi + push edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte [esi - 1] + movzx edx, byte [edi - 1] + sub eax, edx + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm new file mode 100644 index 000000000..0aa371a47 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push esi + push edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [esi + edx - 1] ; eax <- End of Source + cmp esi, edi + jae .0 + cmp eax, edi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +.0: + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz .1 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx ; edx <- remaining bytes to copy + rep movsb +.1: + mov ecx, edx + and edx, 15 + shr ecx, 4 ; ecx <- # of DQwords to copy + jz @CopyBytes + add esp, -16 + movdqu [esp], xmm0 ; save xmm0 +.2: + movdqu xmm0, [esi] ; esi may not be 16-bytes aligned + movntdq [edi], xmm0 ; edi should be 16-bytes aligned + add esi, 16 + add edi, 16 + loop .2 + mfence + movdqu xmm0, [esp] ; restore xmm0 + add esp, 16 ; stack cleanup + jmp @CopyBytes +@CopyBackward: + mov esi, eax ; esi <- Last byte in Source + lea edi, [edi + edx - 1] ; edi <- Last byte in Destination + std +@CopyBytes: + mov ecx, edx + rep movsb + cld + mov eax, [esp + 12] ; eax <- Destination as return value + pop edi + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm new file mode 100644 index 000000000..c3bfb7110 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push edi + mov edi, [esp + 8] ; edi <- Buffer + mov edx, [esp + 12] ; edx <- Length + xor ecx, ecx ; ecx <- 0 + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz @Is16BytesZero + cmp ecx, edx + cmova ecx, edx ; bytes before the 16-byte boundary + sub edx, ecx + xor eax, eax ; eax <- 0, also set ZF + repe scasb + jnz @ReturnFalse ; ZF=0 means non-zero element found +@Is16BytesZero: + mov ecx, edx + and edx, 15 + shr ecx, 4 + jz @IsBytesZero +.0: + pxor xmm0, xmm0 ; xmm0 <- 0 + pcmpeqb xmm0, [edi] ; check zero for 16 bytes + pmovmskb eax, xmm0 ; eax <- compare results + cmp eax, 0xffff + jnz @ReturnFalse + add edi, 16 + loop .0 +@IsBytesZero: + mov ecx, edx + xor eax, eax ; eax <- 0, also set ZF + repe scasb + jnz @ReturnFalse ; ZF=0 means non-zero element found + pop edi + mov eax, 1 ; return TRUE + ret +@ReturnFalse: + pop edi + xor eax, eax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm new file mode 100644 index 000000000..7a3332b53 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm new file mode 100644 index 000000000..9d602f0f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm new file mode 100644 index 000000000..674bcf03e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +.0: + cmp eax, [edi] + lea edi, [edi + 8] + loopne .0 + jne .1 + cmp edx, [edi - 4] + jecxz .1 + jne .0 +.1: + lea eax, [edi - 8] + cmovne eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm new file mode 100644 index 000000000..9244e559b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm new file mode 100644 index 000000000..24313cb4b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm @@ -0,0 +1,67 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.nasm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push edi + mov edx, [esp + 12] ; edx <- Count + mov edi, [esp + 8] ; edi <- Buffer + mov al, [esp + 16] ; al <- Value + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz .0 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosb +.0: + mov ecx, edx + and edx, 15 + shr ecx, 4 ; ecx <- # of DQwords to set + jz @SetBytes + mov ah, al ; ax <- Value | (Value << 8) + add esp, -16 + movdqu [esp], xmm0 ; save xmm0 + movd xmm0, eax + pshuflw xmm0, xmm0, 0 ; xmm0[0..63] <- Value repeats 8 times + movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times +.1: + movntdq [edi], xmm0 ; edi should be 16-byte aligned + add edi, 16 + loop .1 + mfence + movdqu xmm0, [esp] ; restore xmm0 + add esp, 16 ; stack cleanup +@SetBytes: + mov ecx, edx + rep stosb + mov eax, [esp + 8] ; eax <- Buffer as return value + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm new file mode 100644 index 000000000..6e308b559 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.nasm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push edi + mov edx, [esp + 12] + mov edi, [esp + 8] + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + mov eax, [esp + 16] + jz .0 + shr ecx, 1 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosw +.0: + mov ecx, edx + and edx, 7 + shr ecx, 3 + jz @SetWords + movd xmm0, eax + pshuflw xmm0, xmm0, 0 + movlhps xmm0, xmm0 +.1: + movntdq [edi], xmm0 ; edi should be 16-byte aligned + add edi, 16 + loop .1 + mfence +@SetWords: + mov ecx, edx + rep stosw + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm new file mode 100644 index 000000000..2cfc8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.nasm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push edi + mov edx, [esp + 12] + mov edi, [esp + 8] + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + mov eax, [esp + 16] + jz .0 + shr ecx, 2 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosd +.0: + mov ecx, edx + and edx, 3 + shr ecx, 2 + jz @SetDwords + movd xmm0, eax + pshufd xmm0, xmm0, 0 +.1: + movntdq [edi], xmm0 + add edi, 16 + loop .1 + mfence +@SetDwords: + mov ecx, edx + rep stosd + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm new file mode 100644 index 000000000..e153495a6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.nasm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + mov eax, [esp + 4] ; eax <- Buffer + mov ecx, [esp + 8] ; ecx <- Count + test al, 8 + mov edx, eax + movq xmm0, qword [esp + 12] + jz .0 + movq qword [edx], xmm0 + add edx, 8 + dec ecx +.0: + shr ecx, 1 + jz @SetQwords + movlhps xmm0, xmm0 +.1: + movntdq [edx], xmm0 + lea edx, [edx + 16] + loop .1 + mfence +@SetQwords: + jnc .2 + movq qword [edx], xmm0 +.2: + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm new file mode 100644 index 000000000..cd34006f5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.nasm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push edi + mov edi, [esp + 8] + mov edx, [esp + 12] + xor ecx, ecx + sub ecx, edi + xor eax, eax + and ecx, 15 + jz .0 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosb +.0: + mov ecx, edx + and edx, 15 + shr ecx, 4 + jz @ZeroBytes + pxor xmm0, xmm0 +.1: + movntdq [edi], xmm0 + add edi, 16 + loop .1 + mfence +@ZeroBytes: + mov ecx, edx + rep stosb + mov eax, [esp + 8] + pop edi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h new file mode 100644 index 000000000..ce376afda --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h @@ -0,0 +1,245 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include +#include +#include +#include + +/** + Copy Length bytes from Source to Destination. + + @param DestinationBuffer The target of the copy request. + @param SourceBuffer The place to copy from. + @param Length The number of bytes to copy. + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Length The number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer. + @param SourceBuffer The second memory buffer. + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return A pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c new file mode 100644 index 000000000..9ac46416a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c new file mode 100644 index 000000000..e504deb9e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c new file mode 100644 index 000000000..fbb376236 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm new file mode 100644 index 000000000..5514ab663 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; INTN +; EFIAPI +; InternalMemCompareMem ( +; IN CONST VOID *DestinationBuffer, +; IN CONST VOID *SourceBuffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + push rsi + push rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte [rsi - 1] + movzx rdx, byte [rdi - 1] + sub rax, rdx + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm new file mode 100644 index 000000000..33545712b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; CopyMem.nasm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; EFIAPI +; InternalMemCopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + push rsi + push rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rsi + r8 - 1] ; r9 <- Last byte of Source + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae .0 ; Copy forward if Source > Destination + cmp r9, rdi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +.0: + xor rcx, rcx + sub rcx, rdi ; rcx <- -rdi + and rcx, 15 ; rcx + rsi should be 16 bytes aligned + jz .1 ; skip if rcx == 0 + cmp rcx, r8 + cmova rcx, r8 + sub r8, rcx + rep movsb +.1: + mov rcx, r8 + and r8, 15 + shr rcx, 4 ; rcx <- # of DQwords to copy + jz @CopyBytes + movdqa [rsp + 0x18], xmm0 ; save xmm0 on stack +.2: + movdqu xmm0, [rsi] ; rsi may not be 16-byte aligned + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rsi, 16 + add rdi, 16 + loop .2 + mfence + movdqa xmm0, [rsp + 0x18] ; restore xmm0 + jmp @CopyBytes ; copy remaining bytes +@CopyBackward: + mov rsi, r9 ; rsi <- Last byte of Source + lea rdi, [rdi + r8 - 1] ; rdi <- Last byte of Destination + std +@CopyBytes: + mov rcx, r8 + rep movsb + cld + pop rdi + pop rsi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm new file mode 100644 index 000000000..42e5f3f84 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm @@ -0,0 +1,70 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; IsZeroBuffer.nasm +; +; Abstract: +; +; IsZeroBuffer function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; BOOLEAN +; EFIAPI +; InternalMemIsZeroBuffer ( +; IN CONST VOID *Buffer, +; IN UINTN Length +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemIsZeroBuffer) +ASM_PFX(InternalMemIsZeroBuffer): + push rdi + mov rdi, rcx ; rdi <- Buffer + xor rcx, rcx ; rcx <- 0 + sub rcx, rdi + and rcx, 15 ; rcx + rdi aligns on 16-byte boundary + jz @Is16BytesZero + cmp rcx, rdx ; Length already in rdx + cmova rcx, rdx ; bytes before the 16-byte boundary + sub rdx, rcx + xor rax, rax ; rax <- 0, also set ZF + repe scasb + jnz @ReturnFalse ; ZF=0 means non-zero element found +@Is16BytesZero: + mov rcx, rdx + and rdx, 15 + shr rcx, 4 + jz @IsBytesZero +.0: + pxor xmm0, xmm0 ; xmm0 <- 0 + pcmpeqb xmm0, [rdi] ; check zero for 16 bytes + pmovmskb eax, xmm0 ; eax <- compare results + ; nasm doesn't support 64-bit destination + ; for pmovmskb + cmp eax, 0xffff + jnz @ReturnFalse + add rdi, 16 + loop .0 +@IsBytesZero: + mov rcx, rdx + xor rax, rax ; rax <- 0, also set ZF + repe scasb + jnz @ReturnFalse ; ZF=0 means non-zero element found + pop rdi + mov rax, 1 ; return TRUE + ret +@ReturnFalse: + pop rdi + xor rax, rax + ret ; return FALSE + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm new file mode 100644 index 000000000..eb385a4a2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem16 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT16 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm new file mode 100644 index 000000000..6fccdf2d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem32 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm new file mode 100644 index 000000000..6659aef44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem64 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + push rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm new file mode 100644 index 000000000..16fd931c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances contain the same copy of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; BaseMemoryLibOptDxe +; BaseMemoryLibOptPei +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; CONST VOID * +; EFIAPI +; InternalMemScanMem8 ( +; IN CONST VOID *Buffer, +; IN UINTN Length, +; IN UINT8 Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + push rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm new file mode 100644 index 000000000..5bd1c2262 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem.nasm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push rdi + mov rdi, rcx ; rdi <- Buffer + mov al, r8b ; al <- Value + mov r9, rdi ; r9 <- Buffer as return value + xor rcx, rcx + sub rcx, rdi + and rcx, 15 ; rcx + rdi aligns on 16-byte boundary + jz .0 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosb +.0: + mov rcx, rdx + and rdx, 15 + shr rcx, 4 + jz @SetBytes + mov ah, al ; ax <- Value repeats twice + movdqa [rsp + 0x10], xmm0 ; save xmm0 + movd xmm0, eax ; xmm0[0..16] <- Value repeats twice + pshuflw xmm0, xmm0, 0 ; xmm0[0..63] <- Value repeats 8 times + movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times +.1: + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rdi, 16 + loop .1 + mfence + movdqa xmm0, [rsp + 0x10] ; restore xmm0 +@SetBytes: + mov ecx, edx ; high 32 bits of rcx are always zero + rep stosb + mov rax, r9 ; rax <- Return value + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm new file mode 100644 index 000000000..90d159820 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem16.nasm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + push rdi + mov rdi, rcx + mov r9, rdi + xor rcx, rcx + sub rcx, rdi + and rcx, 15 + mov rax, r8 + jz .0 + shr rcx, 1 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosw +.0: + mov rcx, rdx + and edx, 7 + shr rcx, 3 + jz @SetWords + movd xmm0, eax + pshuflw xmm0, xmm0, 0 + movlhps xmm0, xmm0 +.1: + movntdq [rdi], xmm0 + add rdi, 16 + loop .1 + mfence +@SetWords: + mov ecx, edx + rep stosw + mov rax, r9 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm new file mode 100644 index 000000000..928e08688 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem32.nasm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + push rdi + mov rdi, rcx + mov r9, rdi + xor rcx, rcx + sub rcx, rdi + and rcx, 15 + mov rax, r8 + jz .0 + shr rcx, 2 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosd +.0: + mov rcx, rdx + and edx, 3 + shr rcx, 2 + jz @SetDwords + movd xmm0, eax + pshufd xmm0, xmm0, 0 +.1: + movntdq [rdi], xmm0 + add rdi, 16 + loop .1 + mfence +@SetDwords: + mov ecx, edx + rep stosd + mov rax, r9 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm new file mode 100644 index 000000000..d77181054 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; SetMem64.nasm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemSetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + mov rax, rcx ; rax <- Buffer + xchg rcx, rdx ; rcx <- Count & rdx <- Buffer + test dl, 8 + movq xmm0, r8 + jz .0 + mov [rdx], r8 + add rdx, 8 + dec rcx +.0: + shr rcx, 1 + jz @SetQwords + movlhps xmm0, xmm0 +.1: + movntdq [rdx], xmm0 + lea rdx, [rdx + 16] + loop .1 + mfence +@SetQwords: + jnc .2 + mov [rdx], r8 +.2: + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm new file mode 100644 index 000000000..5ddcae9ca --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ZeroMem.nasm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; VOID * +; InternalMemZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + push rdi + mov rdi, rcx + xor rcx, rcx + xor eax, eax + sub rcx, rdi + and rcx, 15 + mov r8, rdi + jz .0 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosb +.0: + mov rcx, rdx + and edx, 15 + shr rcx, 4 + jz @ZeroBytes + pxor xmm0, xmm0 +.1: + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rdi, 16 + loop .1 + mfence +@ZeroBytes: + mov ecx, edx + rep stosb + mov rax, r8 + pop rdi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c new file mode 100644 index 000000000..650a76148 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c @@ -0,0 +1,1448 @@ +/** @file + An OrderedCollectionLib instance that provides a red-black tree + implementation, and allocates and releases tree nodes with + MemoryAllocationLib. + + This library instance is useful when a fast associative container is needed. + Worst case time complexity is O(log n) for Find(), Next(), Prev(), Min(), + Max(), Insert(), and Delete(), where "n" is the number of elements in the + tree. Complete ordered traversal takes O(n) time. + + The implementation is also useful as a fast priority queue. + + Copyright (C) 2014, Red Hat, Inc. + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +typedef enum { + RedBlackTreeRed, + RedBlackTreeBlack +} RED_BLACK_TREE_COLOR; + +// +// Incomplete types and convenience typedefs are present in the library class +// header. Beside completing the types, we introduce typedefs here that reflect +// the implementation closely. +// +typedef ORDERED_COLLECTION RED_BLACK_TREE; +typedef ORDERED_COLLECTION_ENTRY RED_BLACK_TREE_NODE; +typedef ORDERED_COLLECTION_USER_COMPARE RED_BLACK_TREE_USER_COMPARE; +typedef ORDERED_COLLECTION_KEY_COMPARE RED_BLACK_TREE_KEY_COMPARE; + +struct ORDERED_COLLECTION { + RED_BLACK_TREE_NODE *Root; + RED_BLACK_TREE_USER_COMPARE UserStructCompare; + RED_BLACK_TREE_KEY_COMPARE KeyCompare; +}; + +struct ORDERED_COLLECTION_ENTRY { + VOID *UserStruct; + RED_BLACK_TREE_NODE *Parent; + RED_BLACK_TREE_NODE *Left; + RED_BLACK_TREE_NODE *Right; + RED_BLACK_TREE_COLOR Color; +}; + + +/** + Retrieve the user structure linked by the specified tree node. + + Read-only operation. + + @param[in] Node Pointer to the tree node whose associated user structure we + want to retrieve. The caller is responsible for passing a + non-NULL argument. + + @return Pointer to user structure linked by Node. +**/ +VOID * +EFIAPI +OrderedCollectionUserStruct ( + IN CONST RED_BLACK_TREE_NODE *Node + ) +{ + return Node->UserStruct; +} + +/** + A slow function that asserts that the tree is a valid red-black tree, and + that it orders user structures correctly. + + Read-only operation. + + This function uses the stack for recursion and is not recommended for + "production use". + + @param[in] Tree The tree to validate. +**/ +VOID +RedBlackTreeValidate ( + IN CONST RED_BLACK_TREE *Tree + ); + + +/** + Allocate and initialize the RED_BLACK_TREE structure. + + Allocation occurs via MemoryAllocationLib's AllocatePool() function. + + @param[in] UserStructCompare This caller-provided function will be used to + order two user structures linked into the + tree, during the insertion procedure. + + @param[in] KeyCompare This caller-provided function will be used to + order the standalone search key against user + structures linked into the tree, during the + lookup procedure. + + @retval NULL If allocation failed. + + @return Pointer to the allocated, initialized RED_BLACK_TREE structure, + otherwise. +**/ +RED_BLACK_TREE * +EFIAPI +OrderedCollectionInit ( + IN RED_BLACK_TREE_USER_COMPARE UserStructCompare, + IN RED_BLACK_TREE_KEY_COMPARE KeyCompare + ) +{ + RED_BLACK_TREE *Tree; + + Tree = AllocatePool (sizeof *Tree); + if (Tree == NULL) { + return NULL; + } + + Tree->Root = NULL; + Tree->UserStructCompare = UserStructCompare; + Tree->KeyCompare = KeyCompare; + + if (FeaturePcdGet (PcdValidateOrderedCollection)) { + RedBlackTreeValidate (Tree); + } + return Tree; +} + + +/** + Check whether the tree is empty (has no nodes). + + Read-only operation. + + @param[in] Tree The tree to check for emptiness. + + @retval TRUE The tree is empty. + + @retval FALSE The tree is not empty. +**/ +BOOLEAN +EFIAPI +OrderedCollectionIsEmpty ( + IN CONST RED_BLACK_TREE *Tree + ) +{ + return (BOOLEAN)(Tree->Root == NULL); +} + + +/** + Uninitialize and release an empty RED_BLACK_TREE structure. + + Read-write operation. + + Release occurs via MemoryAllocationLib's FreePool() function. + + It is the caller's responsibility to delete all nodes from the tree before + calling this function. + + @param[in] Tree The empty tree to uninitialize and release. +**/ +VOID +EFIAPI +OrderedCollectionUninit ( + IN RED_BLACK_TREE *Tree + ) +{ + ASSERT (OrderedCollectionIsEmpty (Tree)); + FreePool (Tree); +} + + +/** + Look up the tree node that links the user structure that matches the + specified standalone key. + + Read-only operation. + + @param[in] Tree The tree to search for StandaloneKey. + + @param[in] StandaloneKey The key to locate among the user structures linked + into Tree. StandaloneKey will be passed to + Tree->KeyCompare(). + + @retval NULL StandaloneKey could not be found. + + @return The tree node that links to the user structure matching + StandaloneKey, otherwise. +**/ +RED_BLACK_TREE_NODE * +EFIAPI +OrderedCollectionFind ( + IN CONST RED_BLACK_TREE *Tree, + IN CONST VOID *StandaloneKey + ) +{ + RED_BLACK_TREE_NODE *Node; + + Node = Tree->Root; + while (Node != NULL) { + INTN Result; + + Result = Tree->KeyCompare (StandaloneKey, Node->UserStruct); + if (Result == 0) { + break; + } + Node = (Result < 0) ? Node->Left : Node->Right; + } + return Node; +} + + +/** + Find the tree node of the minimum user structure stored in the tree. + + Read-only operation. + + @param[in] Tree The tree to return the minimum node of. The user structure + linked by the minimum node compares less than all other user + structures in the tree. + + @retval NULL If Tree is empty. + + @return The tree node that links the minimum user structure, otherwise. +**/ +RED_BLACK_TREE_NODE * +EFIAPI +OrderedCollectionMin ( + IN CONST RED_BLACK_TREE *Tree + ) +{ + RED_BLACK_TREE_NODE *Node; + + Node = Tree->Root; + if (Node == NULL) { + return NULL; + } + while (Node->Left != NULL) { + Node = Node->Left; + } + return Node; +} + + +/** + Find the tree node of the maximum user structure stored in the tree. + + Read-only operation. + + @param[in] Tree The tree to return the maximum node of. The user structure + linked by the maximum node compares greater than all other + user structures in the tree. + + @retval NULL If Tree is empty. + + @return The tree node that links the maximum user structure, otherwise. +**/ +RED_BLACK_TREE_NODE * +EFIAPI +OrderedCollectionMax ( + IN CONST RED_BLACK_TREE *Tree + ) +{ + RED_BLACK_TREE_NODE *Node; + + Node = Tree->Root; + if (Node == NULL) { + return NULL; + } + while (Node->Right != NULL) { + Node = Node->Right; + } + return Node; +} + + +/** + Get the tree node of the least user structure that is greater than the one + linked by Node. + + Read-only operation. + + @param[in] Node The node to get the successor node of. + + @retval NULL If Node is NULL, or Node is the maximum node of its containing + tree (ie. Node has no successor node). + + @return The tree node linking the least user structure that is greater + than the one linked by Node, otherwise. +**/ +RED_BLACK_TREE_NODE * +EFIAPI +OrderedCollectionNext ( + IN CONST RED_BLACK_TREE_NODE *Node + ) +{ + RED_BLACK_TREE_NODE *Walk; + CONST RED_BLACK_TREE_NODE *Child; + + if (Node == NULL) { + return NULL; + } + + // + // If Node has a right subtree, then the successor is the minimum node of + // that subtree. + // + Walk = Node->Right; + if (Walk != NULL) { + while (Walk->Left != NULL) { + Walk = Walk->Left; + } + return Walk; + } + + // + // Otherwise we have to ascend as long as we're our parent's right child (ie. + // ascending to the left). + // + Child = Node; + Walk = Child->Parent; + while (Walk != NULL && Child == Walk->Right) { + Child = Walk; + Walk = Child->Parent; + } + return Walk; +} + + +/** + Get the tree node of the greatest user structure that is less than the one + linked by Node. + + Read-only operation. + + @param[in] Node The node to get the predecessor node of. + + @retval NULL If Node is NULL, or Node is the minimum node of its containing + tree (ie. Node has no predecessor node). + + @return The tree node linking the greatest user structure that is less + than the one linked by Node, otherwise. +**/ +RED_BLACK_TREE_NODE * +EFIAPI +OrderedCollectionPrev ( + IN CONST RED_BLACK_TREE_NODE *Node + ) +{ + RED_BLACK_TREE_NODE *Walk; + CONST RED_BLACK_TREE_NODE *Child; + + if (Node == NULL) { + return NULL; + } + + // + // If Node has a left subtree, then the predecessor is the maximum node of + // that subtree. + // + Walk = Node->Left; + if (Walk != NULL) { + while (Walk->Right != NULL) { + Walk = Walk->Right; + } + return Walk; + } + + // + // Otherwise we have to ascend as long as we're our parent's left child (ie. + // ascending to the right). + // + Child = Node; + Walk = Child->Parent; + while (Walk != NULL && Child == Walk->Left) { + Child = Walk; + Walk = Child->Parent; + } + return Walk; +} + + +/** + Rotate tree nodes around Pivot to the right. + + Parent Parent + | | + Pivot LeftChild + / . . \_ + LeftChild Node1 ---> Node2 Pivot + . \ / . + Node2 LeftRightChild LeftRightChild Node1 + + The ordering Node2 < LeftChild < LeftRightChild < Pivot < Node1 is kept + intact. Parent (if any) is either at the left extreme or the right extreme of + this ordering, and that relation is also kept intact. + + Edges marked with a dot (".") don't change during rotation. + + Internal read-write operation. + + @param[in,out] Pivot The tree node to rotate other nodes right around. It + is the caller's responsibility to ensure that + Pivot->Left is not NULL. + + @param[out] NewRoot If Pivot has a parent node on input, then the + function updates Pivot's original parent on output + according to the rotation, and NewRoot is not + accessed. + + If Pivot has no parent node on input (ie. Pivot is + the root of the tree), then the function stores the + new root node of the tree in NewRoot. +**/ +VOID +RedBlackTreeRotateRight ( + IN OUT RED_BLACK_TREE_NODE *Pivot, + OUT RED_BLACK_TREE_NODE **NewRoot + ) +{ + RED_BLACK_TREE_NODE *Parent; + RED_BLACK_TREE_NODE *LeftChild; + RED_BLACK_TREE_NODE *LeftRightChild; + + Parent = Pivot->Parent; + LeftChild = Pivot->Left; + LeftRightChild = LeftChild->Right; + + Pivot->Left = LeftRightChild; + if (LeftRightChild != NULL) { + LeftRightChild->Parent = Pivot; + } + LeftChild->Parent = Parent; + if (Parent == NULL) { + *NewRoot = LeftChild; + } else { + if (Pivot == Parent->Left) { + Parent->Left = LeftChild; + } else { + Parent->Right = LeftChild; + } + } + LeftChild->Right = Pivot; + Pivot->Parent = LeftChild; +} + + +/** + Rotate tree nodes around Pivot to the left. + + Parent Parent + | | + Pivot RightChild + . \ / . + Node1 RightChild ---> Pivot Node2 + /. . \_ + RightLeftChild Node2 Node1 RightLeftChild + + The ordering Node1 < Pivot < RightLeftChild < RightChild < Node2 is kept + intact. Parent (if any) is either at the left extreme or the right extreme of + this ordering, and that relation is also kept intact. + + Edges marked with a dot (".") don't change during rotation. + + Internal read-write operation. + + @param[in,out] Pivot The tree node to rotate other nodes left around. It + is the caller's responsibility to ensure that + Pivot->Right is not NULL. + + @param[out] NewRoot If Pivot has a parent node on input, then the + function updates Pivot's original parent on output + according to the rotation, and NewRoot is not + accessed. + + If Pivot has no parent node on input (ie. Pivot is + the root of the tree), then the function stores the + new root node of the tree in NewRoot. +**/ +VOID +RedBlackTreeRotateLeft ( + IN OUT RED_BLACK_TREE_NODE *Pivot, + OUT RED_BLACK_TREE_NODE **NewRoot + ) +{ + RED_BLACK_TREE_NODE *Parent; + RED_BLACK_TREE_NODE *RightChild; + RED_BLACK_TREE_NODE *RightLeftChild; + + Parent = Pivot->Parent; + RightChild = Pivot->Right; + RightLeftChild = RightChild->Left; + + Pivot->Right = RightLeftChild; + if (RightLeftChild != NULL) { + RightLeftChild->Parent = Pivot; + } + RightChild->Parent = Parent; + if (Parent == NULL) { + *NewRoot = RightChild; + } else { + if (Pivot == Parent->Left) { + Parent->Left = RightChild; + } else { + Parent->Right = RightChild; + } + } + RightChild->Left = Pivot; + Pivot->Parent = RightChild; +} + + +/** + Insert (link) a user structure into the tree. + + Read-write operation. + + This function allocates the new tree node with MemoryAllocationLib's + AllocatePool() function. + + @param[in,out] Tree The tree to insert UserStruct into. + + @param[out] Node The meaning of this optional, output-only + parameter depends on the return value of the + function. + + When insertion is successful (RETURN_SUCCESS), + Node is set on output to the new tree node that + now links UserStruct. + + When insertion fails due to lack of memory + (RETURN_OUT_OF_RESOURCES), Node is not changed. + + When insertion fails due to key collision (ie. + another user structure is already in the tree that + compares equal to UserStruct), with return value + RETURN_ALREADY_STARTED, then Node is set on output + to the node that links the colliding user + structure. This enables "find-or-insert" in one + function call, or helps with later removal of the + colliding element. + + @param[in] UserStruct The user structure to link into the tree. + UserStruct is ordered against in-tree user + structures with the Tree->UserStructCompare() + function. + + @retval RETURN_SUCCESS Insertion successful. A new tree node has + been allocated, linking UserStruct. The new + tree node is reported back in Node (if the + caller requested it). + + Existing RED_BLACK_TREE_NODE pointers into + Tree remain valid. For example, on-going + iterations in the caller can continue with + OrderedCollectionNext() / + OrderedCollectionPrev(), and they will + return the new node at some point if user + structure order dictates it. + + @retval RETURN_OUT_OF_RESOURCES AllocatePool() failed to allocate memory for + the new tree node. The tree has not been + changed. Existing RED_BLACK_TREE_NODE + pointers into Tree remain valid. + + @retval RETURN_ALREADY_STARTED A user structure has been found in the tree + that compares equal to UserStruct. The node + linking the colliding user structure is + reported back in Node (if the caller + requested it). The tree has not been + changed. Existing RED_BLACK_TREE_NODE + pointers into Tree remain valid. +**/ +RETURN_STATUS +EFIAPI +OrderedCollectionInsert ( + IN OUT RED_BLACK_TREE *Tree, + OUT RED_BLACK_TREE_NODE **Node OPTIONAL, + IN VOID *UserStruct + ) +{ + RED_BLACK_TREE_NODE *Tmp; + RED_BLACK_TREE_NODE *Parent; + INTN Result; + RETURN_STATUS Status; + RED_BLACK_TREE_NODE *NewRoot; + + Tmp = Tree->Root; + Parent = NULL; + Result = 0; + + // + // First look for a collision, saving the last examined node for the case + // when there's no collision. + // + while (Tmp != NULL) { + Result = Tree->UserStructCompare (UserStruct, Tmp->UserStruct); + if (Result == 0) { + break; + } + Parent = Tmp; + Tmp = (Result < 0) ? Tmp->Left : Tmp->Right; + } + + if (Tmp != NULL) { + if (Node != NULL) { + *Node = Tmp; + } + Status = RETURN_ALREADY_STARTED; + goto Done; + } + + // + // no collision, allocate a new node + // + Tmp = AllocatePool (sizeof *Tmp); + if (Tmp == NULL) { + Status = RETURN_OUT_OF_RESOURCES; + goto Done; + } + if (Node != NULL) { + *Node = Tmp; + } + + // + // reference the user structure from the node + // + Tmp->UserStruct = UserStruct; + + // + // Link the node as a child to the correct side of the parent. + // If there's no parent, the new node is the root node in the tree. + // + Tmp->Parent = Parent; + Tmp->Left = NULL; + Tmp->Right = NULL; + if (Parent == NULL) { + Tree->Root = Tmp; + Tmp->Color = RedBlackTreeBlack; + Status = RETURN_SUCCESS; + goto Done; + } + if (Result < 0) { + Parent->Left = Tmp; + } else { + Parent->Right = Tmp; + } + Tmp->Color = RedBlackTreeRed; + + // + // Red-black tree properties: + // + // #1 Each node is either red or black (RED_BLACK_TREE_NODE.Color). + // + // #2 Each leaf (ie. a pseudo-node pointed-to by a NULL valued + // RED_BLACK_TREE_NODE.Left or RED_BLACK_TREE_NODE.Right field) is black. + // + // #3 Each red node has two black children. + // + // #4 For any node N, and for any leaves L1 and L2 reachable from N, the + // paths N..L1 and N..L2 contain the same number of black nodes. + // + // #5 The root node is black. + // + // By replacing a leaf with a red node above, only property #3 may have been + // broken. (Note that this is the only edge across which property #3 might + // not hold in the entire tree.) Restore property #3. + // + + NewRoot = Tree->Root; + while (Tmp != NewRoot && Parent->Color == RedBlackTreeRed) { + RED_BLACK_TREE_NODE *GrandParent; + RED_BLACK_TREE_NODE *Uncle; + + // + // Tmp is not the root node. Tmp is red. Tmp's parent is red. (Breaking + // property #3.) + // + // Due to property #5, Tmp's parent cannot be the root node, hence Tmp's + // grandparent exists. + // + // Tmp's grandparent is black, because property #3 is only broken between + // Tmp and Tmp's parent. + // + GrandParent = Parent->Parent; + + if (Parent == GrandParent->Left) { + Uncle = GrandParent->Right; + if (Uncle != NULL && Uncle->Color == RedBlackTreeRed) { + // + // GrandParent (black) + // / \_ + // Parent (red) Uncle (red) + // | + // Tmp (red) + // + + Parent->Color = RedBlackTreeBlack; + Uncle->Color = RedBlackTreeBlack; + GrandParent->Color = RedBlackTreeRed; + + // + // GrandParent (red) + // / \_ + // Parent (black) Uncle (black) + // | + // Tmp (red) + // + // We restored property #3 between Tmp and Tmp's parent, without + // breaking property #4. However, we may have broken property #3 + // between Tmp's grandparent and Tmp's great-grandparent (if any), so + // repeat the loop for Tmp's grandparent. + // + // If Tmp's grandparent has no parent, then the loop will terminate, + // and we will have broken property #5, by coloring the root red. We'll + // restore property #5 after the loop, without breaking any others. + // + Tmp = GrandParent; + Parent = Tmp->Parent; + } else { + // + // Tmp's uncle is black (satisfied by the case too when Tmp's uncle is + // NULL, see property #2). + // + + if (Tmp == Parent->Right) { + // + // GrandParent (black): D + // / \_ + // Parent (red): A Uncle (black): E + // \_ + // Tmp (red): B + // \_ + // black: C + // + // Rotate left, pivoting on node A. This keeps the breakage of + // property #3 in the same spot, and keeps other properties intact + // (because both Tmp and its parent are red). + // + Tmp = Parent; + RedBlackTreeRotateLeft (Tmp, &NewRoot); + Parent = Tmp->Parent; + + // + // With the rotation we reached the same configuration as if Tmp had + // been a left child to begin with. + // + // GrandParent (black): D + // / \_ + // Parent (red): B Uncle (black): E + // / \_ + // Tmp (red): A black: C + // + ASSERT (GrandParent == Parent->Parent); + } + + Parent->Color = RedBlackTreeBlack; + GrandParent->Color = RedBlackTreeRed; + + // + // Property #3 is now restored, but we've broken property #4. Namely, + // paths going through node E now see a decrease in black count, while + // paths going through node B don't. + // + // GrandParent (red): D + // / \_ + // Parent (black): B Uncle (black): E + // / \_ + // Tmp (red): A black: C + // + + RedBlackTreeRotateRight (GrandParent, &NewRoot); + + // + // Property #4 has been restored for node E, and preserved for others. + // + // Parent (black): B + // / \_ + // Tmp (red): A [GrandParent] (red): D + // / \_ + // black: C [Uncle] (black): E + // + // This configuration terminates the loop because Tmp's parent is now + // black. + // + } + } else { + // + // Symmetrical to the other branch. + // + Uncle = GrandParent->Left; + if (Uncle != NULL && Uncle->Color == RedBlackTreeRed) { + Parent->Color = RedBlackTreeBlack; + Uncle->Color = RedBlackTreeBlack; + GrandParent->Color = RedBlackTreeRed; + Tmp = GrandParent; + Parent = Tmp->Parent; + } else { + if (Tmp == Parent->Left) { + Tmp = Parent; + RedBlackTreeRotateRight (Tmp, &NewRoot); + Parent = Tmp->Parent; + ASSERT (GrandParent == Parent->Parent); + } + Parent->Color = RedBlackTreeBlack; + GrandParent->Color = RedBlackTreeRed; + RedBlackTreeRotateLeft (GrandParent, &NewRoot); + } + } + } + + NewRoot->Color = RedBlackTreeBlack; + Tree->Root = NewRoot; + Status = RETURN_SUCCESS; + +Done: + if (FeaturePcdGet (PcdValidateOrderedCollection)) { + RedBlackTreeValidate (Tree); + } + return Status; +} + + +/** + Check if a node is black, allowing for leaf nodes (see property #2). + + This is a convenience shorthand. + + param[in] Node The node to check. Node may be NULL, corresponding to a leaf. + + @return If Node is NULL or colored black. +**/ +BOOLEAN +NodeIsNullOrBlack ( + IN CONST RED_BLACK_TREE_NODE *Node + ) +{ + return (BOOLEAN)(Node == NULL || Node->Color == RedBlackTreeBlack); +} + + +/** + Delete a node from the tree, unlinking the associated user structure. + + Read-write operation. + + @param[in,out] Tree The tree to delete Node from. + + @param[in] Node The tree node to delete from Tree. The caller is + responsible for ensuring that Node belongs to + Tree, and that Node is non-NULL and valid. Node is + typically an earlier return value, or output + parameter, of: + + - OrderedCollectionFind(), for deleting a node by + user structure key, + + - OrderedCollectionMin() / OrderedCollectionMax(), + for deleting the minimum / maximum node, + + - OrderedCollectionNext() / + OrderedCollectionPrev(), for deleting a node + found during an iteration, + + - OrderedCollectionInsert() with return value + RETURN_ALREADY_STARTED, for deleting a node + whose linked user structure caused collision + during insertion. + + Given a non-empty Tree, Tree->Root is also a valid + Node argument (typically used for simplicity in + loops that empty the tree completely). + + Node is released with MemoryAllocationLib's + FreePool() function. + + Existing RED_BLACK_TREE_NODE pointers (ie. + iterators) *different* from Node remain valid. For + example: + + - OrderedCollectionNext() / + OrderedCollectionPrev() iterations in the caller + can be continued from Node, if + OrderedCollectionNext() or + OrderedCollectionPrev() is called on Node + *before* OrderedCollectionDelete() is. That is, + fetch the successor / predecessor node first, + then delete Node. + + - On-going iterations in the caller that would + have otherwise returned Node at some point, as + dictated by user structure order, will correctly + reflect the absence of Node after + OrderedCollectionDelete() is called + mid-iteration. + + @param[out] UserStruct If the caller provides this optional output-only + parameter, then on output it is set to the user + structure originally linked by Node (which is now + freed). + + This is a convenience that may save the caller a + OrderedCollectionUserStruct() invocation before + calling OrderedCollectionDelete(), in order to + retrieve the user structure being unlinked. +**/ +VOID +EFIAPI +OrderedCollectionDelete ( + IN OUT RED_BLACK_TREE *Tree, + IN RED_BLACK_TREE_NODE *Node, + OUT VOID **UserStruct OPTIONAL + ) +{ + RED_BLACK_TREE_NODE *NewRoot; + RED_BLACK_TREE_NODE *OrigLeftChild; + RED_BLACK_TREE_NODE *OrigRightChild; + RED_BLACK_TREE_NODE *OrigParent; + RED_BLACK_TREE_NODE *Child; + RED_BLACK_TREE_NODE *Parent; + RED_BLACK_TREE_COLOR ColorOfUnlinked; + + NewRoot = Tree->Root; + OrigLeftChild = Node->Left, + OrigRightChild = Node->Right, + OrigParent = Node->Parent; + + if (UserStruct != NULL) { + *UserStruct = Node->UserStruct; + } + + // + // After this block, no matter which branch we take: + // - Child will point to the unique (or NULL) original child of the node that + // we will have unlinked, + // - Parent will point to the *position* of the original parent of the node + // that we will have unlinked. + // + if (OrigLeftChild == NULL || OrigRightChild == NULL) { + // + // Node has at most one child. We can connect that child (if any) with + // Node's parent (if any), unlinking Node. This will preserve ordering + // because the subtree rooted in Node's child (if any) remains on the same + // side of Node's parent (if any) that Node was before. + // + Parent = OrigParent; + Child = (OrigLeftChild != NULL) ? OrigLeftChild : OrigRightChild; + ColorOfUnlinked = Node->Color; + + if (Child != NULL) { + Child->Parent = Parent; + } + if (OrigParent == NULL) { + NewRoot = Child; + } else { + if (Node == OrigParent->Left) { + OrigParent->Left = Child; + } else { + OrigParent->Right = Child; + } + } + } else { + // + // Node has two children. We unlink Node's successor, and then link it into + // Node's place, keeping Node's original color. This preserves ordering + // because: + // - Node's left subtree is less than Node, hence less than Node's + // successor. + // - Node's right subtree is greater than Node. Node's successor is the + // minimum of that subtree, hence Node's successor is less than Node's + // right subtree with its minimum removed. + // - Node's successor is in Node's subtree, hence it falls on the same side + // of Node's parent as Node itself. The relinking doesn't change this + // relation. + // + RED_BLACK_TREE_NODE *ToRelink; + + ToRelink = OrigRightChild; + if (ToRelink->Left == NULL) { + // + // OrigRightChild itself is Node's successor, it has no left child: + // + // OrigParent + // | + // Node: B + // / \_ + // OrigLeftChild: A OrigRightChild: E <--- Parent, ToRelink + // \_ + // F <--- Child + // + Parent = OrigRightChild; + Child = OrigRightChild->Right; + } else { + do { + ToRelink = ToRelink->Left; + } while (ToRelink->Left != NULL); + + // + // Node's successor is the minimum of OrigRightChild's proper subtree: + // + // OrigParent + // | + // Node: B + // / \_ + // OrigLeftChild: A OrigRightChild: E <--- Parent + // / + // C <--- ToRelink + // \_ + // D <--- Child + Parent = ToRelink->Parent; + Child = ToRelink->Right; + + // + // Unlink Node's successor (ie. ToRelink): + // + // OrigParent + // | + // Node: B + // / \_ + // OrigLeftChild: A OrigRightChild: E <--- Parent + // / + // D <--- Child + // + // C <--- ToRelink + // + Parent->Left = Child; + if (Child != NULL) { + Child->Parent = Parent; + } + + // + // We start to link Node's unlinked successor into Node's place: + // + // OrigParent + // | + // Node: B C <--- ToRelink + // / \_ + // OrigLeftChild: A OrigRightChild: E <--- Parent + // / + // D <--- Child + // + // + // + ToRelink->Right = OrigRightChild; + OrigRightChild->Parent = ToRelink; + } + + // + // The rest handles both cases, attaching ToRelink (Node's original + // successor) to OrigLeftChild and OrigParent. + // + // Parent, + // OrigParent ToRelink OrigParent + // | | | + // Node: B | Node: B Parent + // v | + // OrigRightChild: E C <--- ToRelink | + // / \ / \ v + // OrigLeftChild: A F OrigLeftChild: A OrigRightChild: E + // ^ / + // | D <--- Child + // Child + // + ToRelink->Left = OrigLeftChild; + OrigLeftChild->Parent = ToRelink; + + // + // Node's color must be preserved in Node's original place. + // + ColorOfUnlinked = ToRelink->Color; + ToRelink->Color = Node->Color; + + // + // Finish linking Node's unlinked successor into Node's place. + // + // Parent, + // Node: B ToRelink Node: B + // | + // OrigParent | OrigParent Parent + // | v | | + // OrigRightChild: E C <--- ToRelink | + // / \ / \ v + // OrigLeftChild: A F OrigLeftChild: A OrigRightChild: E + // ^ / + // | D <--- Child + // Child + // + ToRelink->Parent = OrigParent; + if (OrigParent == NULL) { + NewRoot = ToRelink; + } else { + if (Node == OrigParent->Left) { + OrigParent->Left = ToRelink; + } else { + OrigParent->Right = ToRelink; + } + } + } + + FreePool (Node); + + // + // If the node that we unlinked from its original spot (ie. Node itself, or + // Node's successor), was red, then we broke neither property #3 nor property + // #4: we didn't create any red-red edge between Child and Parent, and we + // didn't change the black count on any path. + // + if (ColorOfUnlinked == RedBlackTreeBlack) { + // + // However, if the unlinked node was black, then we have to transfer its + // "black-increment" to its unique child (pointed-to by Child), lest we + // break property #4 for its ancestors. + // + // If Child is red, we can simply color it black. If Child is black + // already, we can't technically transfer a black-increment to it, due to + // property #1. + // + // In the following loop we ascend searching for a red node to color black, + // or until we reach the root (in which case we can drop the + // black-increment). Inside the loop body, Child has a black value of 2, + // transitorily breaking property #1 locally, but maintaining property #4 + // globally. + // + // Rotations in the loop preserve property #4. + // + while (Child != NewRoot && NodeIsNullOrBlack (Child)) { + RED_BLACK_TREE_NODE *Sibling; + RED_BLACK_TREE_NODE *LeftNephew; + RED_BLACK_TREE_NODE *RightNephew; + + if (Child == Parent->Left) { + Sibling = Parent->Right; + // + // Sibling can never be NULL (ie. a leaf). + // + // If Sibling was NULL, then the black count on the path from Parent to + // Sibling would equal Parent's black value, plus 1 (due to property + // #2). Whereas the black count on the path from Parent to any leaf via + // Child would be at least Parent's black value, plus 2 (due to Child's + // black value of 2). This would clash with property #4. + // + // (Sibling can be black of course, but it has to be an internal node. + // Internality allows Sibling to have children, bumping the black + // counts of paths that go through it.) + // + ASSERT (Sibling != NULL); + if (Sibling->Color == RedBlackTreeRed) { + // + // Sibling's red color implies its children (if any), node C and node + // E, are black (property #3). It also implies that Parent is black. + // + // grandparent grandparent + // | | + // Parent,b:B b:D + // / \ / \_ + // Child,2b:A Sibling,r:D ---> Parent,r:B b:E + // /\ /\_ + // b:C b:E Child,2b:A Sibling,b:C + // + Sibling->Color = RedBlackTreeBlack; + Parent->Color = RedBlackTreeRed; + RedBlackTreeRotateLeft (Parent, &NewRoot); + Sibling = Parent->Right; + // + // Same reasoning as above. + // + ASSERT (Sibling != NULL); + } + + // + // Sibling is black, and not NULL. (Ie. Sibling is a black internal + // node.) + // + ASSERT (Sibling->Color == RedBlackTreeBlack); + LeftNephew = Sibling->Left; + RightNephew = Sibling->Right; + if (NodeIsNullOrBlack (LeftNephew) && + NodeIsNullOrBlack (RightNephew)) { + // + // In this case we can "steal" one black value from Child and Sibling + // each, and pass it to Parent. "Stealing" means that Sibling (black + // value 1) becomes red, Child (black value 2) becomes singly-black, + // and Parent will have to be examined if it can eat the + // black-increment. + // + // Sibling is allowed to become red because both of its children are + // black (property #3). + // + // grandparent Parent + // | | + // Parent,x:B Child,x:B + // / \ / \_ + // Child,2b:A Sibling,b:D ---> b:A r:D + // /\ /\_ + // LeftNephew,b:C RightNephew,b:E b:C b:E + // + Sibling->Color = RedBlackTreeRed; + Child = Parent; + Parent = Parent->Parent; + // + // Continue ascending. + // + } else { + // + // At least one nephew is red. + // + if (NodeIsNullOrBlack (RightNephew)) { + // + // Since the right nephew is black, the left nephew is red. Due to + // property #3, LeftNephew has two black children, hence node E is + // black. + // + // Together with the rotation, this enables us to color node F red + // (because property #3 will be satisfied). We flip node D to black + // to maintain property #4. + // + // grandparent grandparent + // | | + // Parent,x:B Parent,x:B + // /\ /\_ + // Child,2b:A Sibling,b:F ---> Child,2b:A Sibling,b:D + // /\ / \_ + // LeftNephew,r:D RightNephew,b:G b:C RightNephew,r:F + // /\ /\_ + // b:C b:E b:E b:G + // + LeftNephew->Color = RedBlackTreeBlack; + Sibling->Color = RedBlackTreeRed; + RedBlackTreeRotateRight (Sibling, &NewRoot); + Sibling = Parent->Right; + RightNephew = Sibling->Right; + // + // These operations ensure that... + // + } + // + // ... RightNephew is definitely red here, plus Sibling is (still) + // black and non-NULL. + // + ASSERT (RightNephew != NULL); + ASSERT (RightNephew->Color == RedBlackTreeRed); + ASSERT (Sibling != NULL); + ASSERT (Sibling->Color == RedBlackTreeBlack); + // + // In this case we can flush the extra black-increment immediately, + // restoring property #1 for Child (node A): we color RightNephew + // (node E) from red to black. + // + // In order to maintain property #4, we exchange colors between + // Parent and Sibling (nodes B and D), and rotate left around Parent + // (node B). The transformation doesn't change the black count + // increase incurred by each partial path, eg. + // - ascending from node A: 2 + x == 1 + 1 + x + // - ascending from node C: y + 1 + x == y + 1 + x + // - ascending from node E: 0 + 1 + x == 1 + x + // + // The color exchange is valid, because even if x stands for red, + // both children of node D are black after the transformation + // (preserving property #3). + // + // grandparent grandparent + // | | + // Parent,x:B x:D + // / \ / \_ + // Child,2b:A Sibling,b:D ---> b:B b:E + // / \ / \_ + // y:C RightNephew,r:E b:A y:C + // + // + Sibling->Color = Parent->Color; + Parent->Color = RedBlackTreeBlack; + RightNephew->Color = RedBlackTreeBlack; + RedBlackTreeRotateLeft (Parent, &NewRoot); + Child = NewRoot; + // + // This terminates the loop. + // + } + } else { + // + // Mirrors the other branch. + // + Sibling = Parent->Left; + ASSERT (Sibling != NULL); + if (Sibling->Color == RedBlackTreeRed) { + Sibling->Color = RedBlackTreeBlack; + Parent->Color = RedBlackTreeRed; + RedBlackTreeRotateRight (Parent, &NewRoot); + Sibling = Parent->Left; + ASSERT (Sibling != NULL); + } + + ASSERT (Sibling->Color == RedBlackTreeBlack); + RightNephew = Sibling->Right; + LeftNephew = Sibling->Left; + if (NodeIsNullOrBlack (RightNephew) && + NodeIsNullOrBlack (LeftNephew)) { + Sibling->Color = RedBlackTreeRed; + Child = Parent; + Parent = Parent->Parent; + } else { + if (NodeIsNullOrBlack (LeftNephew)) { + RightNephew->Color = RedBlackTreeBlack; + Sibling->Color = RedBlackTreeRed; + RedBlackTreeRotateLeft (Sibling, &NewRoot); + Sibling = Parent->Left; + LeftNephew = Sibling->Left; + } + ASSERT (LeftNephew != NULL); + ASSERT (LeftNephew->Color == RedBlackTreeRed); + ASSERT (Sibling != NULL); + ASSERT (Sibling->Color == RedBlackTreeBlack); + Sibling->Color = Parent->Color; + Parent->Color = RedBlackTreeBlack; + LeftNephew->Color = RedBlackTreeBlack; + RedBlackTreeRotateRight (Parent, &NewRoot); + Child = NewRoot; + } + } + } + + if (Child != NULL) { + Child->Color = RedBlackTreeBlack; + } + } + + Tree->Root = NewRoot; + + if (FeaturePcdGet (PcdValidateOrderedCollection)) { + RedBlackTreeValidate (Tree); + } +} + + +/** + Recursively check the red-black tree properties #1 to #4 on a node. + + @param[in] Node The root of the subtree to validate. + + @retval The black-height of Node's parent. +**/ +UINT32 +RedBlackTreeRecursiveCheck ( + IN CONST RED_BLACK_TREE_NODE *Node + ) +{ + UINT32 LeftHeight; + UINT32 RightHeight; + + // + // property #2 + // + if (Node == NULL) { + return 1; + } + + // + // property #1 + // + ASSERT (Node->Color == RedBlackTreeRed || Node->Color == RedBlackTreeBlack); + + // + // property #3 + // + if (Node->Color == RedBlackTreeRed) { + ASSERT (NodeIsNullOrBlack (Node->Left)); + ASSERT (NodeIsNullOrBlack (Node->Right)); + } + + // + // property #4 + // + LeftHeight = RedBlackTreeRecursiveCheck (Node->Left); + RightHeight = RedBlackTreeRecursiveCheck (Node->Right); + ASSERT (LeftHeight == RightHeight); + + return (Node->Color == RedBlackTreeBlack) + LeftHeight; +} + + +/** + A slow function that asserts that the tree is a valid red-black tree, and + that it orders user structures correctly. + + Read-only operation. + + This function uses the stack for recursion and is not recommended for + "production use". + + @param[in] Tree The tree to validate. +**/ +VOID +RedBlackTreeValidate ( + IN CONST RED_BLACK_TREE *Tree + ) +{ + UINT32 BlackHeight; + UINT32 ForwardCount; + UINT32 BackwardCount; + CONST RED_BLACK_TREE_NODE *Last; + CONST RED_BLACK_TREE_NODE *Node; + + DEBUG ((DEBUG_VERBOSE, "%a: Tree=%p\n", __FUNCTION__, Tree)); + + // + // property #5 + // + ASSERT (NodeIsNullOrBlack (Tree->Root)); + + // + // check the other properties + // + BlackHeight = RedBlackTreeRecursiveCheck (Tree->Root) - 1; + + // + // forward ordering + // + Last = OrderedCollectionMin (Tree); + ForwardCount = (Last != NULL); + for (Node = OrderedCollectionNext (Last); Node != NULL; + Node = OrderedCollectionNext (Last)) { + ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) < 0); + Last = Node; + ++ForwardCount; + } + + // + // backward ordering + // + Last = OrderedCollectionMax (Tree); + BackwardCount = (Last != NULL); + for (Node = OrderedCollectionPrev (Last); Node != NULL; + Node = OrderedCollectionPrev (Last)) { + ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) > 0); + Last = Node; + ++BackwardCount; + } + + ASSERT (ForwardCount == BackwardCount); + + DEBUG ((DEBUG_VERBOSE, "%a: Tree=%p BlackHeight=%Ld Count=%Ld\n", + __FUNCTION__, Tree, (INT64)BlackHeight, (INT64)ForwardCount)); +} diff --git a/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf new file mode 100644 index 000000000..57983ac4a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf @@ -0,0 +1,44 @@ +## @file +# An OrderedCollectionLib instance that provides a red-black tree +# implementation, and allocates and releases tree nodes with +# MemoryAllocationLib. +# +# This library instance is useful when a fast associative container is needed. +# Worst case time complexity is O(log n) for Find(), Next(), Prev(), Min(), +# Max(), Insert(), and Delete(), where "n" is the number of elements in the +# tree. Complete ordered traversal takes O(n) time. +# +# The implementation is also useful as a fast priority queue. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# Copyright (C) 2014, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseOrderedCollectionRedBlackTreeLib + MODULE_UNI_FILE = BaseOrderedCollectionRedBlackTreeLib.uni + FILE_GUID = 699F73C3-0058-484C-A9E5-61189276A985 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OrderedCollectionLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseOrderedCollectionRedBlackTreeLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + MemoryAllocationLib + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdValidateOrderedCollection ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni new file mode 100644 index 000000000..661f676e0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni @@ -0,0 +1,24 @@ +// /** @file +// An OrderedCollectionLib instance that provides a red-black tree +// +// implementation, and allocates and releases tree nodes with +// MemoryAllocationLib. +// +// This library instance is useful when a fast associative container is needed. +// Worst case time complexity is O(log n) for Find(), Next(), Prev(), Min(), +// Max(), Insert(), and Delete(), where "n" is the number of elements in the +// tree. Complete ordered traversal takes O(n) time. +// +// The implementation is also useful as a fast priority queue. +// +// Copyright (C) 2014, Red Hat, Inc. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "An OrderedCollectionLib instance that provides a red-black tree implementation." + +#string STR_MODULE_DESCRIPTION #language en-US "An OrderedCollectionLib instance that provides a red-black tree implementation." + diff --git a/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf b/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf new file mode 100644 index 000000000..0ce75b2ac --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf @@ -0,0 +1,37 @@ +## @file +# Instance of PCD Library without support of dynamic PCD entries. +# +# PCD Library that only provides access to Feature Flag, Fixed At Build, +# and Binary Patch typed PCD entries. Access to Dynamic PCD entries is ignored. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePcdLibNull + MODULE_UNI_FILE = BasePcdLibNull.uni + FILE_GUID = 40096a3a-5c2a-4fbc-aef7-5475dd7ab334 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PcdLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PcdLib.c + +[LibraryClasses] + DebugLib + BaseMemoryLib + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni b/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni new file mode 100644 index 000000000..9c79ee110 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCD Library without support of dynamic PCD entries. +// +// PCD Library that only provides access to Feature Flag, Fixed At Build, +// and Binary Patch typed PCD entries. Access to Dynamic PCD entries is ignored. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCD Library without support of dynamic PCD entries" + +#string STR_MODULE_DESCRIPTION #language en-US "PCD Library that only provides access to Feature Flag, Fixed At Build, and Binary Patch typed PCD entries. Access to Dynamic PCD entries is ignored." + diff --git a/roms/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c b/roms/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c new file mode 100644 index 000000000..49447880a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c @@ -0,0 +1,1474 @@ +/** @file + A emptry template implementation of PCD Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + + +/** + This function provides a means by which SKU support can be established in the PCD infrastructure. + + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @return Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + ASSERT (FALSE); + + return 0; +} + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + Returns the size of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value + specified by Buffer and SizeOfBuffer. Buffer is returned. + If SizeOfBuffer is greater than the maximum size support by TokenNumber, + then set SizeOfBuffer to the maximum size supported by TokenNumber and + return NULL to indicate that the set operation was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and NULL must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (FALSE); + + return NULL; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (FALSE); + + return FALSE; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size + supported by TokenNumber and return NULL to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pinter to the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); + + return NULL; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (FALSE); + + return FALSE; +} +#endif + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet8S ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet16S ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet32S ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet64S ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and EFI_INVALID_PARAMETER must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetPtrS ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetBoolS ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx8S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx16S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx32S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx64S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExPtrS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExBoolS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (FALSE); + + return RETURN_INVALID_PARAMETER; +} + +/** + Set up a notification function that is called when a specified token is set. + + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (FALSE); +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + + Disable a notification function that was previously established with LibPcdCallbackOnSet(). + + If NotificationFunction is NULL, then ASSERT(). + If LibPcdCallbackOnSet() was not previously called with Guid, TokenNumber, + and NotificationFunction, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (FALSE); +} + + + +/** + Retrieves the next token in a token space. + + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. + + If TokenNumber is not 0 and is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] TokenNumber The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @return The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + Used to retrieve the list of available PCD token space GUIDs. + + Returns the PCD token space GUID that follows TokenSpaceGuid in the list of token spaces + in the platform. + If TokenSpaceGuid is NULL, then a pointer to the first PCD token spaces returned. + If TokenSpaceGuid is the last PCD token space GUID in the list, then NULL is returned. + + @param TokenSpaceGuid The pointer to a PCD token space GUID. + + @return The next valid token namespace. + +**/ +GUID * +EFIAPI +LibPcdGetNextTokenSpace ( + IN CONST GUID *TokenSpaceGuid + ) +{ + ASSERT (FALSE); + + return NULL; +} + + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer that was set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtr ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return (VOID *) Buffer; +} + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrS ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return RETURN_SUCCESS; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtrAndSize ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return (VOID *) Buffer; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrAndSizeS ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return RETURN_SUCCESS; +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the default token space specified, then ASSERT(). + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfo ( + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + ASSERT (FALSE); +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfoEx ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + ASSERT (FALSE); +} + +/** + Retrieve the currently set SKU Id. + + @return The currently set SKU Id. If the platform has not set at a SKU Id, then the + default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU + Id is returned. +**/ +UINTN +EFIAPI +LibPcdGetSku ( + VOID + ) +{ + ASSERT (FALSE); + + return 0; +} + diff --git a/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf b/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf new file mode 100644 index 000000000..09fe0f8f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf @@ -0,0 +1,37 @@ +## @file +# Instance of PCI CF8 Library using I/O ports 0xCF8 and 0xCFC. +# +# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. +# Layers on top of an I/O Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciCf8Lib + MODULE_UNI_FILE = BasePciCf8Lib.uni + FILE_GUID = 472ab06d-9810-4c00-bb7f-dad1828fc1ab + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciCf8Lib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciCf8Lib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + diff --git a/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni b/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni new file mode 100644 index 000000000..a428269ab --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI CF8 Library using I/O ports 0xCF8 and 0xCFC. +// +// PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. +// Layers on top of an I/O Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI CF8 Library using I/O ports 0xCF8 and 0xCFC" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. Layers on top of an I/O Library instance." + diff --git a/roms/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c b/roms/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c new file mode 100644 index 000000000..ba4190ab6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c @@ -0,0 +1,1778 @@ +/** @file + PCI CF8 Library functions that use I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. + Layers on top of an I/O Library instance. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +// +// Declare I/O Ports used to perform PCI Confguration Cycles +// +#define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8 +#define PCI_CONFIGURATION_DATA_PORT 0xCFC + +/** + Convert a PCI Library address to PCI CF8 formatted address. + + Declare macro to convert PCI Library address to PCI CF8 formatted address. + Bit fields of PCI Library and CF8 formatted address is as follows: + PCI Library formatted address CF8 Formatted Address + ============================= ====================== + Bits 00..11 Register Bits 00..07 Register + Bits 12..14 Function Bits 08..10 Function + Bits 15..19 Device Bits 11..15 Device + Bits 20..27 Bus Bits 16..23 Bus + Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ) + Bits 31..31 Must be 1 + + @param A The address to convert. + + @retval The coverted address. + +**/ +#define PCI_TO_CF8_ADDRESS(A) \ + ((UINT32) ((((A) >> 4) & 0x00ffff00) | ((A) & 0xfc) | 0x80000000)) + +/** + Assert the validity of a PCI CF8 address. A valid PCI CF8 address should contain 1's + only in the low 28 bits, excluding bits 08..11. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A,M) \ + ASSERT (((A) & (~0xffff0ff | (M))) == 0) + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciCf8RegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + return RETURN_SUCCESS; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Read8 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead8 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Write8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Or8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8And8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAnd8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8AndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAndThenOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldRead8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAnd8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAndThenOr8( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAndThenOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Read16 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead16 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Write16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Or16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8And16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAnd16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8AndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAndThenOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldRead16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAnd16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAndThenOr16( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAndThenOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Read32 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead32 (PCI_CONFIGURATION_DATA_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Write32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Or32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoOr32 ( + PCI_CONFIGURATION_DATA_PORT, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8And32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAnd32 ( + PCI_CONFIGURATION_DATA_PORT, + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8AndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoAndThenOr32 ( + PCI_CONFIGURATION_DATA_PORT, + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldRead32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldOr32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAnd32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + AndData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAndThenOr32( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoBitFieldAndThenOr32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + AndData, + OrData + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size read from StartAddress. + +**/ +UINTN +EFIAPI +PciCf8ReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciCf8Read8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 ((UINT16 *)Buffer, (UINT16) PciCf8Read16 (StartAddress)); + + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 ((UINT32 *)Buffer, (UINT32) PciCf8Read32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 ((UINT16 *)Buffer, (UINT16) PciCf8Read16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciCf8Read8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciCf8WriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciCf8Write8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciCf8Write16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciCf8Write32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciCf8Write16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciCf8Write8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf b/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf new file mode 100644 index 000000000..a7edb74cd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf @@ -0,0 +1,41 @@ +## @file +# Instance of PCI Express Library using the 256 MB PCI Express MMIO window. +# +# PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +# PCI Configuration cycles. Layers on top of an I/O Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciExpressLib + MODULE_UNI_FILE = BasePciExpressLib.uni + FILE_GUID = 287e50f4-a188-4699-b907-3e4080ca5688 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciExpressLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciExpressLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + PcdLib + DebugLib + IoLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni b/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni new file mode 100644 index 000000000..98010ef2f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI Express Library using the 256 MB PCI Express MMIO window. +// +// PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +// PCI Configuration cycles. Layers on top of an I/O Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Express Library using the 256 MB PCI Express MMIO window" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Express Library that uses the 256 MB PCI Express MMIO window to perform PCI Configuration cycles. Layers on top of an I/O Library instance." + diff --git a/roms/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c b/roms/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c new file mode 100644 index 000000000..99a166c36 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c @@ -0,0 +1,1413 @@ +/** @file + Functions in this library instance make use of MMIO functions in IoLib to + access memory mapped PCI configuration space. + + All assertions for I/O operations are handled in MMIO functions in the IoLib + Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include +#include + + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A) \ + ASSERT (((A) & ~0xfffffff) == 0) + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration + registers associated with that PCI device may be accessed after SetVirtualAddressMap() + is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciExpressRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return RETURN_UNSUPPORTED; +} + +/** + Gets the base address of PCI Express. + + This internal functions retrieves PCI Express Base Address via a PCD entry + PcdPciExpressBaseAddress. + + @return The base address of PCI Express. + +**/ +VOID* +GetPciExpressBaseAddress ( + VOID + ) +{ + return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr8 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr16 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr32 ( + (UINTN) GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size read data from StartAddress. + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress)); + + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf b/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf new file mode 100644 index 000000000..5d3f1471c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf @@ -0,0 +1,35 @@ +## @file +# Instance of PCI Library based on PCI CF8 Library. +# +# PCI Library that uses I/O ports 0xCF8 and 0xCFC to perform +# PCI Configuration cycles. Layers on top of one PCI CF8 Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciLibCf8 + MODULE_UNI_FILE = BasePciLibCf8.uni + FILE_GUID = 28bde99c-e8a7-4e3e-9a8a-e66cd64f31c6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PciCf8Lib + diff --git a/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni b/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni new file mode 100644 index 000000000..37ff4d01a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI Library based on PCI CF8 Library. +// +// PCI Library that uses I/O ports 0xCF8 and 0xCFC to perform +// PCI Configuration cycles. Layers on top of one PCI CF8 Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Library based on PCI CF8 Library" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. Layers on top of one PCI CF8 Library instance." + diff --git a/roms/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c b/roms/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c new file mode 100644 index 000000000..a2eb4d9dc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c @@ -0,0 +1,1132 @@ +/** @file + PCI Library functions that use I/O ports 0xCF8 and 0xCFC to perform + PCI Configuration cycles. Layers on top of one PCI CF8 Library instance. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + return PciCf8RegisterForRuntimeAccess (Address); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + return PciCf8Read8 (Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return PciCf8Write8 (Address, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciCf8Or8 (Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciCf8And8 (Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciCf8AndThenOr8 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead8 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciCf8BitFieldWrite8 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciCf8BitFieldOr8 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciCf8BitFieldAnd8 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciCf8BitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + return PciCf8Read16 (Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return PciCf8Write16 (Address, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciCf8Or16 (Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciCf8And16 (Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciCf8AndThenOr16 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead16 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciCf8BitFieldWrite16 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciCf8BitFieldOr16 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciCf8BitFieldAnd16 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciCf8BitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + return PciCf8Read32 (Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return PciCf8Write32 (Address, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciCf8Or32 (Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciCf8And32 (Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciCf8AndThenOr32 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead32 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciCf8BitFieldWrite32 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciCf8BitFieldOr32 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciCf8BitFieldAnd32 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciCf8BitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + return PciCf8ReadBuffer (StartAddress, Size, Buffer); +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + return PciCf8WriteBuffer (StartAddress, Size, Buffer); +} diff --git a/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf new file mode 100644 index 000000000..488db9fd8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf @@ -0,0 +1,36 @@ +## @file +# Instance of PCI Library based on PCI Express Library. +# +# PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI +# Configuration cycles. Layers on one PCI Express Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciLibPciExpress + MODULE_UNI_FILE = BasePciLibPciExpress.uni + FILE_GUID = 8987081e-daeb-44a9-8bef-a195b22d9417 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# + +[Sources] + PciLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PciExpressLib + diff --git a/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni new file mode 100644 index 000000000..ccc456356 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI Library based on PCI Express Library. +// +// PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI +// Configuration cycles. Layers on one PCI Express Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Library based on PCI Express Library" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI Configuration cycles. Layers on an PCI Express Library instance." + diff --git a/roms/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c new file mode 100644 index 000000000..00dd31c12 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c @@ -0,0 +1,1132 @@ +/** @file + PCI Library functions that use the 256 MB PCI Express MMIO window to perform PCI + Configuration cycles. Layers on PCI Express Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + return PciExpressRegisterForRuntimeAccess (Address); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + return PciExpressRead8 (Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return PciExpressWrite8 (Address, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciExpressOr8 (Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciExpressAnd8 (Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressAndThenOr8 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead8 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + return PciExpressRead16 (Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return PciExpressWrite16 (Address, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciExpressOr16 (Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciExpressAnd16 (Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressAndThenOr16 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead16 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + return PciExpressRead32 (Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return PciExpressWrite32 (Address, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciExpressOr32 (Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciExpressAnd32 (Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressAndThenOr32 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead32 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + return PciExpressReadBuffer (StartAddress, Size, Buffer); +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + return PciExpressWriteBuffer (StartAddress, Size, Buffer); +} diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf new file mode 100644 index 000000000..08c6742c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf @@ -0,0 +1,36 @@ +## @file +# Instance of PCI SegmentInfo Library. +# +# Default PCI Segment Information Library that shouldn't be used by real platform. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciSegmentInfoLibNull + MODULE_UNI_FILE = BasePciSegmentInfoLibNull.uni + FILE_GUID = 36B28584-C6AE-4B1B-A473-A51618EE525A + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentInfoLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentInfoLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + DebugLib diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni new file mode 100644 index 000000000..b9807f156 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni @@ -0,0 +1,15 @@ +// /** @file +// Instance of PCI SegmentInfo Library. +// +// Default PCI Segment Information Library that shouldn't be used by real platform. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Default instance of PCI SegmentInfo Library." + +#string STR_MODULE_DESCRIPTION #language en-US "Default PCI Segment Information Library that shouldn't be used by real platform." diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c new file mode 100644 index 000000000..3ec778405 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c @@ -0,0 +1,32 @@ +/** @file + Default PCI Segment Information Library that returns one segment whose + segment base address equals to PcdPciExpressBaseAddress. + + Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Return an array of PCI_SEGMENT_INFO holding the segment information. + + Note: The returned array/buffer is owned by callee. + + @param Count Return the count of segments. + + @retval A callee owned array holding the segment information. +**/ +PCI_SEGMENT_INFO * +EFIAPI +GetPciSegmentInfo ( + UINTN *Count + ) +{ + ASSERT (FALSE); + *Count = 0; + return NULL; +} diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf new file mode 100644 index 000000000..623e9bd28 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf @@ -0,0 +1,38 @@ +## @file +# Instance of PCI Segment Library based on PCI Library. +# +# PCI Segment Library that layers on top of the PCI Library which only +# supports segment 0 PCI configuration access. +# +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciSegmentLibPci + MODULE_UNI_FILE = BasePciSegmentLibPci.uni + FILE_GUID = AABF95D6-F40C-405F-8360-6A59794B8040 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + PciLib + DebugLib diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni new file mode 100644 index 000000000..dcb9bc1ce --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of PCI Segment Library based on PCI Library. +// +// PCI Segment Library that layers on top of the PCI Library which only +// supports segment 0 PCI configuration access. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Segment Library based on PCI Library." + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Library that layers on top of the PCI Library which only supports segment 0 PCI configuration access." diff --git a/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c new file mode 100644 index 000000000..95cab4aed --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c @@ -0,0 +1,1283 @@ +/** @file + PCI Segment Library that layers on top of the PCI Library which only + supports segment 0 PCI configuration access. + + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/** + Assert the validity of a PCI Segment address. + A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63 + and the segment should be 0. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \ + ASSERT (((A) & (0xfffffffff0000000ULL | (M))) == 0) + +/** + Convert the PCI Segment library address to PCI library address. + + @param A The address to convert. +**/ +#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN) (UINT32) A) + +/** + Register a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + return PciRegisterForRuntimeAccess (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return PciRead8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8) (PciSegmentRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return PciRead16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return PciWrite16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PciRead32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address)); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PciWrite32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + + Reads the 32-bit PCI configuration register specified by Address, performs a bitwise + AND between the read result and the value specified by AndData, and writes the result + to the 32-bit PCI configuration register specified by Address. The value written to + the PCI configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*) Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*) Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*) Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*) Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf new file mode 100644 index 000000000..60c1ebd24 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf @@ -0,0 +1,33 @@ +## @file +# Null PE/Coff Extra Action library instances with empty functions. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeCoffExtraActionLibNull + MODULE_UNI_FILE = PeCoffExtraActionLibNull.uni + FILE_GUID = 0EB84DA1-267A-40b4-8347-1F48694C8B47 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeCoffExtraActionLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PeCoffExtraActionLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c new file mode 100644 index 000000000..ac5a1a29a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c @@ -0,0 +1,48 @@ +/** @file + Null PE/Coff Extra Action library instances with empty functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Performs additional actions after a PE/COFF image has been loaded and relocated. + + If ImageContext is NULL, then ASSERT(). + + @param ImageContext The pointer to the image context structure that describes the + PE/COFF image that has already been loaded and relocated. + +**/ +VOID +EFIAPI +PeCoffLoaderRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + ASSERT (ImageContext != NULL); +} + +/** + Performs additional actions just before a PE/COFF image is unloaded. Any resources + that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed. + + If ImageContext is NULL, then ASSERT(). + + @param ImageContext The pointer to the image context structure that describes the + PE/COFF image that is being unloaded. + +**/ +VOID +EFIAPI +PeCoffLoaderUnloadImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + ASSERT (ImageContext != NULL); +} diff --git a/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni new file mode 100644 index 000000000..2ed84d48b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Null PE/Coff Extra Action library instances with empty functions. +// +// Null PE/Coff Extra Action library instances with empty functions. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Null PE/Coff Extra Action library instances with empty functions" + +#string STR_MODULE_DESCRIPTION #language en-US "Null PE/Coff Extra Action library instances with empty functions." + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf new file mode 100644 index 000000000..12ee3d0f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf @@ -0,0 +1,35 @@ +## @file +# PE/COFF Entry Point Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePeCoffGetEntryPointLib + MODULE_UNI_FILE = BasePeCoffGetEntryPointLib.uni + FILE_GUID = be490364-73d2-420d-950e-f6450ca75dfb + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeCoffGetEntryPointLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PeCoffGetEntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni new file mode 100644 index 000000000..f119d0851 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni @@ -0,0 +1,16 @@ +// /** @file +// PE/COFF Entry Point Library implementation. +// +// PE/COFF Entry Point Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PE/COFF Entry Point Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "PE/COFF Entry Point Library implementation." + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c new file mode 100644 index 000000000..02ba83982 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c @@ -0,0 +1,382 @@ +/** @file + Provides the services to get the entry point to a PE/COFF image that has either been + loaded into memory or is executing at it's linked address. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include + +#include + +#define PE_COFF_IMAGE_ALIGN_SIZE 4 + +/** + Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded + into system memory with the PE/COFF Loader Library functions. + + Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry + point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then + return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS. + If Pe32Data is NULL, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + + @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory. + @param EntryPoint The pointer to entry point to the PE/COFF image to return. + + @retval RETURN_SUCCESS EntryPoint was returned. + @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + ASSERT (Pe32Data != NULL); + ASSERT (EntryPoint != NULL); + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + // + // Calculate the entry point relative to the start of the image. + // AddressOfEntryPoint is common for PE32 & PE32+ + // + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize); + return RETURN_SUCCESS; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + return RETURN_SUCCESS; + } + + return RETURN_UNSUPPORTED; +} + + +/** + Returns the machine type of a PE/COFF image. + + Returns the machine type from the PE/COFF image specified by Pe32Data. + If Pe32Data is NULL, then ASSERT(). + + @param Pe32Data The pointer to the PE/COFF image that is loaded in system + memory. + + @return Machine type or zero if not a valid image. + +**/ +UINT16 +EFIAPI +PeCoffLoaderGetMachineType ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DOS_HEADER *DosHdr; + + ASSERT (Pe32Data != NULL); + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + return Hdr.Te->Machine; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + return Hdr.Pe32->FileHeader.Machine; + } + + return 0x0000; +} + +/** + Returns a pointer to the PDB file name for a PE/COFF image that has been + loaded into system memory with the PE/COFF Loader Library functions. + + Returns the PDB file name for the PE/COFF image specified by Pe32Data. If + the PE/COFF image specified by Pe32Data is not a valid, then NULL is + returned. If the PE/COFF image specified by Pe32Data does not contain a + debug directory entry, then NULL is returned. If the debug directory entry + in the PE/COFF image specified by Pe32Data does not contain a PDB file name, + then NULL is returned. + If Pe32Data is NULL, then ASSERT(). + + @param Pe32Data The pointer to the PE/COFF image that is loaded in system + memory. + + @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL + if it cannot be retrieved. + +**/ +VOID * +EFIAPI +PeCoffLoaderGetPdbPointer ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + + ASSERT (Pe32Data != NULL); + + TEImageAdjust = 0; + DirectoryEntry = NULL; + DebugEntry = NULL; + NumberOfRvaAndSizes = 0; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te + + Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + // + // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic. + // It is due to backward-compatibility, for some system might + // generate PE32+ image with PE32 Magic. + // + switch (Hdr.Pe32->FileHeader.Machine) { + case IMAGE_FILE_MACHINE_I386: + // + // Assume PE32 image with IA32 Machine field. + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case IMAGE_FILE_MACHINE_X64: + case IMAGE_FILE_MACHINE_IA64: + // + // Assume PE32+ image with x64 or IA64 Machine field + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: + // + // For unknow Machine field, use Magic in optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // Use PE32+ offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } + } else { + return NULL; + } + + if (DebugEntry == NULL || DirectoryEntry == NULL) { + return NULL; + } + + // + // Scan the directory to find the debug entry. + // + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)); + case CODEVIEW_SIGNATURE_RSDS: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)); + case CODEVIEW_SIGNATURE_MTOC: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)); + default: + break; + } + } + } + } + + return NULL; +} + +/** + Returns the size of the PE/COFF headers + + Returns the size of the PE/COFF header specified by Pe32Data. + If Pe32Data is NULL, then ASSERT(). + + @param Pe32Data The pointer to the PE/COFF image that is loaded in system + memory. + + @return Size of PE/COFF header in bytes or zero if not a valid image. + +**/ +UINT32 +EFIAPI +PeCoffGetSizeOfHeaders ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + UINTN SizeOfHeaders; + + ASSERT (Pe32Data != NULL); + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + } else { + SizeOfHeaders = 0; + } + + return (UINT32) SizeOfHeaders; +} + +/** + Returns PE/COFF image base is loaded in system memory where the input address is in. + + On DEBUG build, searches the PE/COFF image base forward the input address and + returns it. + + @param Address Address located in one PE/COFF image. + + @retval 0 RELEASE build or cannot find the PE/COFF image base. + @retval others PE/COFF image base found. + +**/ +UINTN +EFIAPI +PeCoffSearchImageBase ( + IN UINTN Address + ) +{ + UINTN Pe32Data; + + Pe32Data = 0; + + DEBUG_CODE ( + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + // + // Find Image Base + // + Pe32Data = Address & ~(PE_COFF_IMAGE_ALIGN_SIZE - 1); + while (Pe32Data != 0) { + DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + // + // Make sure PE header address does not overflow and is less than the initial address. + // + if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < Address)) { + if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + break; + } + } + } else { + // + // DOS image header is not present, TE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) && + ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_IA64) || + (Hdr.Te->Machine == IMAGE_FILE_MACHINE_EBC) || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64) || + (Hdr.Te->Machine == IMAGE_FILE_MACHINE_ARM64) || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED)) + ) { + break; + } + } + + // + // Not found the image base, check the previous aligned address + // + Pe32Data -= PE_COFF_IMAGE_ALIGN_SIZE; + } + ); + + return Pe32Data; +} diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c b/roms/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c new file mode 100644 index 000000000..7e868db89 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c @@ -0,0 +1,244 @@ +/** @file + Specific relocation fixups for ARM architecture. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BasePeCoffLibInternals.h" +#include + + +/** + Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and + return the immediate data encoded in the instruction. + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + + @return Immediate address encoded in the instruction + +**/ +UINT16 +ThumbMovtImmediateAddress ( + IN UINT16 *Instruction + ) +{ + UINT32 Movt; + UINT16 Address; + + // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction + // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000 + Movt = (*Instruction << 16) | (*(Instruction + 1)); + + // imm16 = imm4:i:imm3:imm8 + // imm4 -> Bit19:Bit16 + // i -> Bit26 + // imm3 -> Bit14:Bit12 + // imm8 -> Bit7:Bit0 + Address = (UINT16)(Movt & 0x000000ff); // imm8 + Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3 + Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i + return Address; +} + + +/** + Update an ARM MOVT or MOVW immediate instruction immediate data. + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + @param Address New addres to patch into the instruction +**/ +VOID +ThumbMovtImmediatePatch ( + IN OUT UINT16 *Instruction, + IN UINT16 Address + ) +{ + UINT16 Patch; + + // First 16-bit chunk of instruciton + Patch = ((Address >> 12) & 0x000f); // imm4 + Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i + // Mask out instruction bits and or in address + *(Instruction) = (*Instruction & ~0x040f) | Patch; + + // Second 16-bit chunk of instruction + Patch = Address & 0x000000ff; // imm8 + Patch |= ((Address << 4) & 0x00007000); // imm3 + // Mask out instruction bits and or in address + Instruction++; + *Instruction = (*Instruction & ~0x70ff) | Patch; +} + + + +/** + Pass in a pointer to an ARM MOVW/MOVT instruciton pair and + return the immediate data encoded in the two` instruction. + + @param Instructions Pointer to ARM MOVW/MOVT insturction pair + + @return Immediate address encoded in the instructions + +**/ +UINT32 +ThumbMovwMovtImmediateAddress ( + IN UINT16 *Instructions + ) +{ + UINT16 *Word; + UINT16 *Top; + + Word = Instructions; // MOVW + Top = Word + 2; // MOVT + + return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word); +} + + +/** + Update an ARM MOVW/MOVT immediate instruction instruction pair. + + @param Instructions Pointer to ARM MOVW/MOVT instruction pair + @param Address New addres to patch into the instructions +**/ +VOID +ThumbMovwMovtImmediatePatch ( + IN OUT UINT16 *Instructions, + IN UINT32 Address + ) +{ + UINT16 *Word; + UINT16 *Top; + + Word = Instructions; // MOVW + Top = Word + 2; // MOVT + + ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff)); + ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16)); +} + + + +/** + Performs an ARM-based specific relocation fixup and is a no-op on other + instruction sets. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT16 *Fixup16; + UINT32 FixupVal; + + Fixup16 = (UINT16 *) Fixup; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ARM_MOV32T: + FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust; + ThumbMovwMovtImmediatePatch (Fixup16, FixupVal); + + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + // Fixup16 is not aligned so we must copy it. Thumb instructions are streams of 16 bytes. + CopyMem (*FixupData, Fixup16, sizeof (UINT64)); + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_ARM_MOV32A: + ASSERT (FALSE); + // break omitted - ARM instruction encoding not implemented + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} + +/** + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + @param Machine Machine type from the PE Header. + + @return TRUE if this PE/COFF loader can load the image + +**/ +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +{ + if ((Machine == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED) || (Machine == IMAGE_FILE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} + +/** + Performs an ARM-based specific re-relocation fixup and is a no-op on other + instruction sets. This is used to re-relocated the image into the EFI virtual + space for runtime calls. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT16 *Fixup16; + UINT32 FixupVal; + + Fixup16 = (UINT16 *)Fixup; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ARM_MOV32T: + *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); + if (*(UINT64 *) (*FixupData) == ReadUnaligned64 ((UINT64 *)Fixup16)) { + FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust; + ThumbMovwMovtImmediatePatch (Fixup16, FixupVal); + } + *FixupData = *FixupData + sizeof(UINT64); + break; + + case EFI_IMAGE_REL_BASED_ARM_MOV32A: + ASSERT (FALSE); + // break omitted - ARM instruction encoding not implemented + default: + DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n")); + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c new file mode 100644 index 000000000..1102833b9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c @@ -0,0 +1,1944 @@ +/** @file + Base PE/COFF loader supports loading any PE32/PE32+ or TE image, but + only supports relocating IA32, x64, IPF, ARM, RISC-V and EBC images. + + Caution: This file requires additional review when modified. + This library will have external input - PE/COFF image. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + The basic guideline is that caller need provide ImageContext->ImageRead () with the + necessary data range check, to make sure when this library reads PE/COFF image, the + PE image buffer is always in valid range. + This library will also do some additional check for PE header fields. + + PeCoffLoaderGetPeHeader() routine will do basic check for PE/COFF header. + PeCoffLoaderGetImageInfo() routine will do basic check for whole PE/COFF image. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BasePeCoffLibInternals.h" + +/** + Adjust some fields in section header for TE image. + + @param SectionHeader Pointer to the section header. + @param TeStrippedOffset Size adjust for the TE image. + +**/ +VOID +PeCoffLoaderAdjustOffsetForTeImage ( + EFI_IMAGE_SECTION_HEADER *SectionHeader, + UINT32 TeStrippedOffset + ) +{ + SectionHeader->VirtualAddress -= TeStrippedOffset; + SectionHeader->PointerToRawData -= TeStrippedOffset; +} + +/** + Retrieves the PE or TE Header from a PE/COFF or TE image. + + Caution: This function may receive untrusted input. + PE/COFF image is external input, so this routine will + also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, + SizeOfHeader, Section Data Region and Security Data Region be in PE image range. + + @param ImageContext The context of the image being loaded. + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. + + @retval RETURN_SUCCESS The PE or TE Header is read. + @retval Other The error status from reading the PE/COFF or TE image using the ImageRead function. + +**/ +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + UINTN ReadSize; + UINT32 SectionHeaderOffset; + UINT32 Index; + UINT32 HeaderWithoutDataDir; + CHAR8 BufferData; + UINTN NumberOfSections; + EFI_IMAGE_SECTION_HEADER SectionHeader; + + // + // Read the DOS image header to check for its existence + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image + // header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + + // + // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much + // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic + // determines if this is a PE32 or PE32+ image. The magic is in the same + // location in both images. + // + Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + Hdr.Pe32 + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // Use Signature to figure out if we understand the image format + // + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + ImageContext->IsTeImage = TRUE; + ImageContext->Machine = Hdr.Te->Machine; + ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem); + // + // For TeImage, SectionAlignment is undefined to be set to Zero + // ImageSize can be calculated. + // + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 0; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize; + + // + // Check the StrippedSize. + // + if (sizeof (EFI_TE_IMAGE_HEADER) >= (UINT32)Hdr.Te->StrippedSize) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Check the SizeOfHeaders field. + // + if (Hdr.Te->BaseOfCode <= Hdr.Te->StrippedSize) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Read last byte of Hdr.Te->SizeOfHeaders from the file. + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->SizeOfHeaders - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // TE Image Data Directory Entry size is non-zero, but the Data Directory Virtual Address is zero. + // This case is not a valid TE image. + // + if ((Hdr.Te->DataDirectory[0].Size != 0 && Hdr.Te->DataDirectory[0].VirtualAddress == 0) || + (Hdr.Te->DataDirectory[1].Size != 0 && Hdr.Te->DataDirectory[1].VirtualAddress == 0)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + ImageContext->IsTeImage = FALSE; + ImageContext->Machine = Hdr.Pe32->FileHeader.Machine; + + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // 1. Check OptionalHeader.NumberOfRvaAndSizes filed. + // + if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // 2. Check the FileHeader.SizeOfOptionalHeader field. + // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so + // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow. + // + HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER32) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + if (((UINT32)Hdr.Pe32->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) != + Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader; + // + // 3. Check the FileHeader.NumberOfSections field. + // + if (Hdr.Pe32->OptionalHeader.SizeOfImage <= SectionHeaderOffset) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if ((Hdr.Pe32->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32->FileHeader.NumberOfSections) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // 4. Check the OptionalHeader.SizeOfHeaders field. + // + if (Hdr.Pe32->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if (Hdr.Pe32->OptionalHeader.SizeOfHeaders >= Hdr.Pe32->OptionalHeader.SizeOfImage) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if ((Hdr.Pe32->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32->FileHeader.NumberOfSections) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // 4.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file. + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Hdr.Pe32->OptionalHeader.SizeOfHeaders - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data. + // Read the last byte to make sure the data is in the image region. + // The DataDirectory array begin with 1, not 0, so here use < to compare not <=. + // + if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) { + if (Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) { + // + // Check the member data to avoid overflow. + // + if ((UINT32) (~0) - Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress < + Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Read last byte of section header from file + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress + + Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + } + } + + // + // Use PE32 offset + // + ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem; + ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // 1. Check FileHeader.NumberOfRvaAndSizes filed. + // + if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + // + // 2. Check the FileHeader.SizeOfOptionalHeader field. + // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so + // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow. + // + HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER64) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + if (((UINT32)Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) != + Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader; + // + // 3. Check the FileHeader.NumberOfSections field. + // + if (Hdr.Pe32Plus->OptionalHeader.SizeOfImage <= SectionHeaderOffset) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if ((Hdr.Pe32Plus->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32Plus->FileHeader.NumberOfSections) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // 4. Check the OptionalHeader.SizeOfHeaders field. + // + if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders >= Hdr.Pe32Plus->OptionalHeader.SizeOfImage) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + if ((Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32Plus->FileHeader.NumberOfSections) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // 4.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file. + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data. + // Read the last byte to make sure the data is in the image region. + // The DataDirectory array begin with 1, not 0, so here use < to compare not <=. + // + if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) { + if (Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) { + // + // Check the member data to avoid overflow. + // + if ((UINT32) (~0) - Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress < + Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Read last byte of section header from file + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress + + Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + } + } + + // + // Use PE32+ offset + // + ImageContext->ImageType = Hdr.Pe32Plus->OptionalHeader.Subsystem; + ImageContext->ImageSize = (UINT64) Hdr.Pe32Plus->OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders; + } else { + ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE; + return RETURN_UNSUPPORTED; + } + } else { + ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE; + return RETURN_UNSUPPORTED; + } + + if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) { + // + // If the PE/COFF loader does not support the image type return + // unsupported. This library can support lots of types of images + // this does not mean the user of this library can call the entry + // point of the image. + // + return RETURN_UNSUPPORTED; + } + + // + // Check each section field. + // + if (ImageContext->IsTeImage) { + SectionHeaderOffset = sizeof(EFI_TE_IMAGE_HEADER); + NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections); + } else { + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader; + NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections); + } + + for (Index = 0; Index < NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // Adjust some field in Section Header for TE image. + // + if (ImageContext->IsTeImage) { + PeCoffLoaderAdjustOffsetForTeImage (&SectionHeader, (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); + } + + if (SectionHeader.SizeOfRawData > 0) { + // + // Section data should bigger than the Pe header. + // + if (SectionHeader.VirtualAddress < ImageContext->SizeOfHeaders || + SectionHeader.PointerToRawData < ImageContext->SizeOfHeaders) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Check the member data to avoid overflow. + // + if ((UINT32) (~0) - SectionHeader.PointerToRawData < SectionHeader.SizeOfRawData) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + + // + // Base on the ImageRead function to check the section data field. + // Read the last byte to make sure the data is in the image region. + // + Size = 1; + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData - 1, + &Size, + &BufferData + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + } + + // + // Check next section. + // + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + return RETURN_SUCCESS; +} + + +/** + Retrieves information about a PE/COFF image. + + Computes the PeCoffHeaderOffset, IsTeImage, ImageType, ImageAddress, ImageSize, + DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and + DebugDirectoryEntryRva fields of the ImageContext structure. + If ImageContext is NULL, then return RETURN_INVALID_PARAMETER. + If the PE/COFF image accessed through the ImageRead service in the ImageContext + structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED. + If any errors occur while computing the fields of ImageContext, + then the error status is returned in the ImageError field of ImageContext. + If the image is a TE image, then SectionAlignment is set to 0. + The ImageRead and Handle fields of ImageContext structure must be valid prior + to invoking this service. + + Caution: This function may receive untrusted input. + PE/COFF image is external input, so this routine will + also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, + SizeOfHeader, Section Data Region and Security Data Region be in PE image range. + + @param ImageContext The pointer to the image context structure that describes the PE/COFF + image that needs to be examined by this function. + + @retval RETURN_SUCCESS The information on the PE/COFF image was collected. + @retval RETURN_INVALID_PARAMETER ImageContext is NULL. + @retval RETURN_UNSUPPORTED The PE/COFF image is not supported. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN ReadSize; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + UINT32 NumberOfRvaAndSizes; + UINT32 TeStrippedOffset; + + if (ImageContext == NULL) { + return RETURN_INVALID_PARAMETER; + } + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + Hdr.Union = &HdrData; + Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + TeStrippedOffset = 0; + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase; + } else { + // + // Use PE32+ offset + // + ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase; + } + } else { + TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + TeStrippedOffset); + } + + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the debug codeview pointer. + // + ImageContext->DebugDirectoryEntryRva = 0; + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this information in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else if ((ImageContext->IsTeImage) && (Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } + + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader; + + for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset + Index, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + // + // From PeCoff spec, when DebugEntry.RVA == 0 means this debug info will not load into memory. + // Here we will always load EFI_IMAGE_DEBUG_TYPE_CODEVIEW type debug info. so need adjust the + // ImageContext->ImageSize when DebugEntry.RVA == 0. + // + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return RETURN_SUCCESS; + } + } + } + } + } else { + + DebugDirectoryEntry = &Hdr.Te->DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < Hdr.Te->NumberOfSections;) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData - + TeStrippedOffset; + + // + // File offset of the debug directory was found, if this is not the last + // section, then skip to the last section for calculating the image size. + // + if (Index < (UINTN) Hdr.Te->NumberOfSections - 1) { + SectionHeaderOffset += (Hdr.Te->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER); + Index = Hdr.Te->NumberOfSections - 1; + continue; + } + } + + // + // In Te image header there is not a field to describe the ImageSize. + // Actually, the ImageSize equals the RVA plus the VirtualSize of + // the last section mapped into memory (Must be rounded up to + // a multiple of Section Alignment). Per the PE/COFF specification, the + // section headers in the Section Table must appear in order of the RVA + // values for the corresponding sections. So the ImageSize can be determined + // by the RVA and the VirtualSize of the last section header in the + // Section Table. + // + if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) { + ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) - TeStrippedOffset; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset + Index, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + if (Size != ReadSize) { + Status = RETURN_UNSUPPORTED; + } + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index); + return RETURN_SUCCESS; + } + } + } + } + + return RETURN_SUCCESS; +} + + +/** + Converts an image address to the loaded address. + + @param ImageContext The context of the image being loaded. + @param Address The address to be converted to the loaded address. + @param TeStrippedOffset Stripped offset for TE image. + + @return The converted address or NULL if the address can not be converted. + +**/ +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address, + IN UINTN TeStrippedOffset + ) +{ + // + // Make sure that Address and ImageSize is correct for the loaded image. + // + if (Address >= ImageContext->ImageSize + TeStrippedOffset) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address - TeStrippedOffset); +} + +/** + Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage(). + + If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of + ImageContext as the relocation base address. Otherwise, use the DestinationAddress field + of ImageContext as the relocation base address. The caller must allocate the relocation + fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function. + + The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, + ImageSize, DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, + DebugDirectoryEntryRva, EntryPoint, FixupDataSize, CodeView, PdbPointer, and FixupData of + the ImageContext structure must be valid prior to invoking this service. + + If ImageContext is NULL, then ASSERT(). + + Note that if the platform does not maintain coherency between the instruction cache(s) and the data + cache(s) in hardware, then the caller is responsible for performing cache maintenance operations + prior to transferring control to a PE/COFF image that is loaded using this library. + + @param ImageContext The pointer to the image context structure that describes the PE/COFF + image that is being relocated. + + @retval RETURN_SUCCESS The PE/COFF image was relocated. + Extended status information is in the ImageError field of ImageContext. + @retval RETURN_LOAD_ERROR The image in not a valid PE/COFF image. + Extended status information is in the ImageError field of ImageContext. + @retval RETURN_UNSUPPORTED A relocation record type is not supported. + Extended status information is in the ImageError field of ImageContext. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBaseOrg; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *Fixup16; + UINT32 *Fixup32; + UINT64 *Fixup64; + CHAR8 *FixupData; + PHYSICAL_ADDRESS BaseAddress; + UINT32 NumberOfRvaAndSizes; + UINT32 TeStrippedOffset; + + ASSERT (ImageContext != NULL); + + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + // Applies additional environment specific actions to relocate fixups + // to a PE/COFF image if needed + PeCoffLoaderRelocateImageExtraAction (ImageContext); + return RETURN_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress != 0) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + + if (!(ImageContext->IsTeImage)) { + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + TeStrippedOffset = 0; + + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase; + if (Adjust != 0) { + Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress; + } + + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } else { + // + // Use PE32+ offset + // + Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase; + if (Adjust != 0) { + Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress; + } + + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } + + // + // Find the relocation block + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if ((NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC)) { + RelocDir = NULL; + } + } else { + Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress); + TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + Adjust = (UINT64) (BaseAddress - (Hdr.Te->ImageBase + TeStrippedOffset)); + if (Adjust != 0) { + Hdr.Te->ImageBase = (UINT64) (BaseAddress - TeStrippedOffset); + } + + // + // Find the relocation block + // + RelocDir = &Hdr.Te->DataDirectory[0]; + } + + if ((RelocDir != NULL) && (RelocDir->Size > 0)) { + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1, + TeStrippedOffset + ); + if (RelocBase == NULL || RelocBaseEnd == NULL || (UINTN) RelocBaseEnd < (UINTN) RelocBase) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = NULL; + } + RelocBaseOrg = RelocBase; + + // + // If Adjust is not zero, then apply fix ups to the image + // + if (Adjust != 0) { + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while ((UINTN) RelocBase < (UINTN) RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + // + // Add check for RelocBase->SizeOfBlock field. + // + if (RelocBase->SizeOfBlock == 0) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + if ((UINTN)RelocBase > MAX_ADDRESS - RelocBase->SizeOfBlock) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if ((UINTN)RelocEnd > (UINTN)RelocBaseOrg + RelocDir->Size) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress, TeStrippedOffset); + if (FixupBase == NULL) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + // + // Run this relocation record + // + while ((UINTN) Reloc < (UINTN) RelocEnd) { + Fixup = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), TeStrippedOffset); + if (Fixup == NULL) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + Fixup16 = (UINT16 *) Fixup; + *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16))); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *Fixup16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + Fixup16 = (UINT16 *) Fixup; + *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *Fixup16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + Fixup32 = (UINT32 *) Fixup; + *Fixup32 = *Fixup32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *)FixupData = *Fixup32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_DIR64: + Fixup64 = (UINT64 *) Fixup; + *Fixup64 = *Fixup64 + (UINT64) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64)); + *(UINT64 *)(FixupData) = *Fixup64; + FixupData = FixupData + sizeof(UINT64); + } + break; + + default: + // + // The common code does not handle some of the stranger IPF relocations + // PeCoffLoaderRelocateImageEx () adds support for these complex fixups + // on IPF and is a No-Op on other architectures. + // + Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + ASSERT ((UINTN)FixupData <= (UINTN)ImageContext->FixupData + ImageContext->FixupDataSize); + + // + // Adjust the EntryPoint to match the linked-to address + // + if (ImageContext->DestinationAddress != 0) { + ImageContext->EntryPoint -= (UINT64) ImageContext->ImageAddress; + ImageContext->EntryPoint += (UINT64) ImageContext->DestinationAddress; + } + } + + // Applies additional environment specific actions to relocate fixups + // to a PE/COFF image if needed + PeCoffLoaderRelocateImageExtraAction (ImageContext); + + return RETURN_SUCCESS; +} + +/** + Loads a PE/COFF image into memory. + + Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer + specified by the ImageAddress and ImageSize fields of ImageContext. The caller must allocate + the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function. + The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed. + The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize, + DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva + fields of the ImageContext structure must be valid prior to invoking this service. + + If ImageContext is NULL, then ASSERT(). + + Note that if the platform does not maintain coherency between the instruction cache(s) and the data + cache(s) in hardware, then the caller is responsible for performing cache maintenance operations + prior to transferring control to a PE/COFF image that is loaded using this library. + + @param ImageContext The pointer to the image context structure that describes the PE/COFF + image that is being loaded. + + @retval RETURN_SUCCESS The PE/COFF image was loaded into the buffer specified by + the ImageAddress and ImageSize fields of ImageContext. + Extended status information is in the ImageError field of ImageContext. + @retval RETURN_BUFFER_TOO_SMALL The caller did not provide a large enough buffer. + Extended status information is in the ImageError field of ImageContext. + @retval RETURN_LOAD_ERROR The PE/COFF image is an EFI Runtime image with no relocations. + Extended status information is in the ImageError field of ImageContext. + @retval RETURN_INVALID_PARAMETER The image address is invalid. + Extended status information is in the ImageError field of ImageContext. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; + CHAR16 *String; + UINT32 Offset; + UINT32 TeStrippedOffset; + + ASSERT (ImageContext != NULL); + + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context information into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo (&CheckContext); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE; + return RETURN_BUFFER_TOO_SMALL; + } + if (ImageContext->ImageAddress == 0) { + // + // Image cannot be loaded into 0 address. + // + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return RETURN_INVALID_PARAMETER; + } + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return RETURN_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return RETURN_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections); + TeStrippedOffset = 0; + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (void *)(UINTN)ImageContext->ImageAddress + ); + + Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress); + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections); + TeStrippedOffset = (UINT32) Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0; Index < NumberOfSections; Index++) { + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress, TeStrippedOffset); + End = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress + Section->Misc.VirtualSize - 1, TeStrippedOffset); + + // + // If the size of the section is non-zero and the base address or end address resolved to 0, then fail. + // + if ((Size > 0) && ((Base == NULL) || (End == NULL))) { + ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED; + return RETURN_LOAD_ERROR; + } + + if (Section->SizeOfRawData > 0) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData - TeStrippedOffset, + &Size, + Base + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virtual size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + // + // Sizes of AddressOfEntryPoint are different so we need to do this safely + // + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress ( + ImageContext, + (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint, + 0 + ); + } else { + // + // Use PE32+ offset + // + ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress ( + ImageContext, + (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint, + 0 + ); + } + } else { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress ( + ImageContext, + (UINTN)Hdr.Te->AddressOfEntryPoint, + TeStrippedOffset + ); + } + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (!(ImageContext->IsTeImage)) { + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } + + // + // Must use UINT64 here, because there might a case that 32bit loader to load 64bit image. + // + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + DirectoryEntry = &Hdr.Te->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview information if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva, + TeStrippedOffset + ); + if (DebugEntry == NULL) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva, TeStrippedOffset); + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset - TeStrippedOffset, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + case CODEVIEW_SIGNATURE_MTOC: + if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY); + break; + + default: + break; + } + } + } + + // + // Get Image's HII resource section + // + ImageContext->HiiResourceData = 0; + if (!(ImageContext->IsTeImage)) { + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE]; + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE]; + } + + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && DirectoryEntry->Size != 0) { + Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress, 0); + if (Base != NULL) { + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base; + Offset = sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * + (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries); + if (Offset > DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) { + if (ResourceDirectoryEntry->u1.s.NameIsString) { + // + // Check the ResourceDirectoryEntry->u1.s.NameOffset before use it. + // + if (ResourceDirectoryEntry->u1.s.NameOffset >= DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset); + String = &ResourceDirectoryString->String[0]; + + if (ResourceDirectoryString->Length == 3 && + String[0] == L'H' && + String[1] == L'I' && + String[2] == L'I') { + // + // Resource Type "HII" found + // + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Name + // + if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries); + if (Offset > DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Language + // + if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries); + if (Offset > DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + } + } + + // + // Now it ought to be resource Data + // + if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) { + if (ResourceDirectoryEntry->u2.OffsetToData >= DirectoryEntry->Size) { + ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED; + return RETURN_UNSUPPORTED; + } + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (Base + ResourceDirectoryEntry->u2.OffsetToData); + ImageContext->HiiResourceData = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData, 0); + break; + } + } + } + ResourceDirectoryEntry++; + } + } + } + } + + return Status; +} + + +/** + Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI + runtime. + + This function reapplies relocation fixups to the PE/COFF image specified by ImageBase + and ImageSize so the image will execute correctly when the PE/COFF image is mapped + to the address specified by VirtualImageBase. RelocationData must be identical + to the FiuxupData buffer from the PE_COFF_LOADER_IMAGE_CONTEXT structure + after this PE/COFF image was relocated with PeCoffLoaderRelocateImage(). + + Note that if the platform does not maintain coherency between the instruction cache(s) and the data + cache(s) in hardware, then the caller is responsible for performing cache maintenance operations + prior to transferring control to a PE/COFF image that is loaded using this library. + + @param ImageBase The base address of a PE/COFF image that has been loaded + and relocated into system memory. + @param VirtImageBase The request virtual address that the PE/COFF image is to + be fixed up for. + @param ImageSize The size, in bytes, of the PE/COFF image. + @param RelocationData A pointer to the relocation data that was collected when the PE/COFF + image was relocated using PeCoffLoaderRelocateImage(). + +**/ +VOID +EFIAPI +PeCoffLoaderRelocateImageForRuntime ( + IN PHYSICAL_ADDRESS ImageBase, + IN PHYSICAL_ADDRESS VirtImageBase, + IN UINTN ImageSize, + IN VOID *RelocationData + ) +{ + CHAR8 *OldBase; + CHAR8 *NewBase; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY *DataDirectory; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + EFI_IMAGE_BASE_RELOCATION *RelocBaseOrig; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *Fixup16; + UINT32 *Fixup32; + UINT64 *Fixup64; + CHAR8 *FixupData; + UINTN Adjust; + RETURN_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + if (RelocationData == NULL || ImageBase == 0x0 || VirtImageBase == 0x0) { + return; + } + + OldBase = (CHAR8 *)((UINTN)ImageBase); + NewBase = (CHAR8 *)((UINTN)VirtImageBase); + Adjust = (UINTN) NewBase - (UINTN) OldBase; + + ImageContext.ImageAddress = ImageBase; + ImageContext.ImageSize = ImageSize; + + // + // Find the image's relocate dir info + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)OldBase; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // Valid DOS header so get address of PE header + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((CHAR8 *)DosHdr) + DosHdr->e_lfanew); + } else { + // + // No Dos header so assume image starts with PE header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)OldBase; + } + + if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { + // + // Not a valid PE image so Exit + // + return ; + } + + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[0]); + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[0]); + } + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + RelocBase = NULL; + RelocBaseEnd = NULL; + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC; + if ((RelocDir != NULL) && (RelocDir->Size > 0)) { + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (&ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1, + 0 + ); + } + if (RelocBase == NULL || RelocBaseEnd == NULL || (UINTN) RelocBaseEnd < (UINTN) RelocBase) { + // + // relocation block is not valid, just return + // + return; + } + } else { + // + // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image. + // + ASSERT (FALSE); + return ; + } + + // + // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both NULL. + // + ASSERT (RelocBase != NULL && RelocBaseEnd != NULL); + + if (Adjust != 0) { + // + // Run the whole relocation block. And re-fixup data that has not been + // modified. The FixupData is used to see if the image has been modified + // since it was relocated. This is so data sections that have been updated + // by code will not be fixed up, since that would set them back to + // defaults. + // + FixupData = RelocationData; + RelocBaseOrig = RelocBase; + while ((UINTN) RelocBase < (UINTN) RelocBaseEnd) { + // + // Add check for RelocBase->SizeOfBlock field. + // + if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) { + // + // Data invalid, cannot continue to relocate the image, just return. + // + return; + } + + Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock); + if ((UINTN)RelocEnd > (UINTN)RelocBaseOrig + RelocDir->Size) { + return; + } + + FixupBase = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress, 0); + if (FixupBase == NULL) { + return; + } + + // + // Run this relocation record + // + while ((UINTN) Reloc < (UINTN) RelocEnd) { + + Fixup = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), 0); + if (Fixup == NULL) { + return; + } + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + Fixup16 = (UINT16 *) Fixup; + if (*(UINT16 *) FixupData == *Fixup16) { + *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16))); + } + + FixupData = FixupData + sizeof (UINT16); + break; + + case EFI_IMAGE_REL_BASED_LOW: + Fixup16 = (UINT16 *) Fixup; + if (*(UINT16 *) FixupData == *Fixup16) { + *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff)); + } + + FixupData = FixupData + sizeof (UINT16); + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + Fixup32 = (UINT32 *) Fixup; + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + if (*(UINT32 *) FixupData == *Fixup32) { + *Fixup32 = *Fixup32 + (UINT32) Adjust; + } + + FixupData = FixupData + sizeof (UINT32); + break; + + case EFI_IMAGE_REL_BASED_DIR64: + Fixup64 = (UINT64 *)Fixup; + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64)); + if (*(UINT64 *) FixupData == *Fixup64) { + *Fixup64 = *Fixup64 + (UINT64)Adjust; + } + + FixupData = FixupData + sizeof (UINT64); + break; + + default: + // + // Only Itanium requires ConvertPeImage_Ex + // + Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (RETURN_ERROR (Status)) { + return ; + } + } + // + // Next relocation record + // + Reloc += 1; + } + // + // next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + } +} + + +/** + Reads contents of a PE/COFF image from a buffer in system memory. + + This is the default implementation of a PE_COFF_LOADER_READ_FILE function + that assumes FileHandle pointer to the beginning of a PE/COFF image. + This function reads contents of the PE/COFF image that starts at the system memory + address specified by FileHandle. The read operation copies ReadSize bytes from the + PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer. + The size of the buffer actually read is returned in ReadSize. + + The caller must make sure the FileOffset and ReadSize within the file scope. + + If FileHandle is NULL, then ASSERT(). + If ReadSize is NULL, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param FileHandle The pointer to base of the input stream + @param FileOffset Offset into the PE/COFF image to begin the read operation. + @param ReadSize On input, the size in bytes of the requested read operation. + On output, the number of bytes actually read. + @param Buffer Output buffer that contains the data read from the PE/COFF image. + + @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into + the buffer. +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderImageReadFromMemory ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +{ + ASSERT (ReadSize != NULL); + ASSERT (FileHandle != NULL); + ASSERT (Buffer != NULL); + + CopyMem (Buffer, ((UINT8 *)FileHandle) + FileOffset, *ReadSize); + return RETURN_SUCCESS; +} + +/** + Unloads a loaded PE/COFF image from memory and releases its taken resource. + Releases any environment specific resources that were allocated when the image + specified by ImageContext was loaded using PeCoffLoaderLoadImage(). + + For NT32 emulator, the PE/COFF image loaded by system needs to release. + For real platform, the PE/COFF image loaded by Core doesn't needs to be unloaded, + this function can simply return RETURN_SUCCESS. + + If ImageContext is NULL, then ASSERT(). + + @param ImageContext The pointer to the image context structure that describes the PE/COFF + image to be unloaded. + + @retval RETURN_SUCCESS The PE/COFF image was unloaded successfully. +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderUnloadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + // + // Applies additional environment specific actions to unload a + // PE/COFF image if needed + // + PeCoffLoaderUnloadImageExtraAction (ImageContext); + return RETURN_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf new file mode 100644 index 000000000..110b6d5a0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf @@ -0,0 +1,56 @@ +## @file +# PE/COFF Loader Library implementation. +# The IPF version library supports loading IPF and EBC PE/COFF image. +# The IA32 version library support loading IA32, X64 and EBC PE/COFF images. +# The X64 version library support loading IA32, X64 and EBC PE/COFF images. +# The RISC-V version library support loading RISC-V images. +# +# Caution: This module requires additional review when modified. +# This library will have external input - PE/COFF image. +# This external input must be validated carefully to avoid security issue like +# buffer overflow, integer overflow. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePeCoffLib + MODULE_UNI_FILE = BasePeCoffLib.uni + FILE_GUID = 556f5d10-7309-4af4-b80a-8196bd60946f + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeCoffLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# + +[Sources] + BasePeCoffLibInternals.h + BasePeCoff.c + +[Sources.IA32, Sources.X64, Sources.EBC, Sources.AARCH64] + PeCoffLoaderEx.c + +[Sources.ARM] + Arm/PeCoffLoaderEx.c + +[Sources.RISCV64] + RiscV/PeCoffLoaderEx.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + PeCoffExtraActionLib + BaseMemoryLib + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni new file mode 100644 index 000000000..55417029f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni @@ -0,0 +1,26 @@ +// /** @file +// PE/COFF Loader Library implementation. +// +// The IPF version library supports loading IPF and EBC PE/COFF image. +// The IA32 version library support loading IA32, X64 and EBC PE/COFF images. +// The X64 version library support loading IA32, X64 and EBC PE/COFF images. +// The RISC-V version library support loading RISC-V32 and RISC-V64 PE/COFF images. +// +// Caution: This module requires additional review when modified. +// This library will have external input - PE/COFF image. +// This external input must be validated carefully to avoid security issue like +// buffer overflow, integer overflow. +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PE/COFF Loader Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "The IPF version library supports loading IPF and EBC PE/COFF images. The IA32 version library support loading IA32, X64 and EBC PE/COFF images. The X64 version library support loading IA32, X64 and EBC PE/COFF images. Caution: This module requires additional review when modified. This library will have external input: PE/COFF image. This external input must be validated carefully to avoid security issues like buffer overflow and integer overflow." + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h new file mode 100644 index 000000000..3ee56e0e5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h @@ -0,0 +1,136 @@ +/** @file + Declaration of internal functions in PE/COFF Lib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_PECOFF_LIB_INTERNALS__ +#define __BASE_PECOFF_LIB_INTERNALS__ + +#include +#include +#include +#include +#include +#include + +// +// Macro definitions for RISC-V architecture. +// +#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1)) +#define RISCV_IMM_BITS 12 +#define RISCV_IMM_REACH (1LL< + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BasePeCoffLibInternals.h" + + +/** + Performs an Itanium-based specific relocation fixup and is a no-op on other + instruction sets. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + The IA32/X64 version PE/COFF loader/relocater both support IA32, X64 and EBC images. + + @param Machine The machine type from the PE Header. + + @return TRUE if this PE/COFF loader can load the image + +**/ +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +{ + if ((Machine == IMAGE_FILE_MACHINE_I386) || (Machine == IMAGE_FILE_MACHINE_X64) || + (Machine == IMAGE_FILE_MACHINE_EBC) || (Machine == IMAGE_FILE_MACHINE_ARM64)) { + return TRUE; + } + + return FALSE; +} + +/** + Performs an Itanium-based specific re-relocation fixup and is a no-op on other + instruction sets. This is used to re-relocated the image into the EFI virtual + space for runtime calls. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + return RETURN_UNSUPPORTED; +} + diff --git a/roms/edk2/MdePkg/Library/BasePeCoffLib/RiscV/PeCoffLoaderEx.c b/roms/edk2/MdePkg/Library/BasePeCoffLib/RiscV/PeCoffLoaderEx.c new file mode 100644 index 000000000..23170a660 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePeCoffLib/RiscV/PeCoffLoaderEx.c @@ -0,0 +1,133 @@ +/** @file + PE/Coff loader for RISC-V PE image + + Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "BasePeCoffLibInternals.h" +#include + +/** + Performs an RISC-V specific relocation fixup and is a no-op on + other instruction sets. + RISC-V splits 32-bit fixup into 20bit and 12-bit with two relocation + types. We have to know the lower 12-bit fixup first then we can deal + carry over on high 20-bit fixup. So we log the high 20-bit in + FixupData. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT32 Value; + UINT32 Value2; + UINT32 *RiscVHi20Fixup; + + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_RISCV_HI20: + *(UINT64 *)(*FixupData) = (UINT64)(UINTN)Fixup; + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12I: + RiscVHi20Fixup = (UINT32 *)(*(UINT64 *)(*FixupData)); + if (RiscVHi20Fixup != NULL) { + + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) |\ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) |\ + (RV_X (*(UINT32 *)Fixup, 0, 20)); + } + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12S: + RiscVHi20Fixup = (UINT32 *)(*(UINT64 *)(*FixupData)); + if (RiscVHi20Fixup != NULL) { + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + Value2 = *(UINT32 *)Fixup & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + break; + + default: + return RETURN_UNSUPPORTED; + + } + return RETURN_SUCCESS; +} + +/** + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + @param Machine Machine type from the PE Header. + + @return TRUE if this PE/COFF loader can load the image + +**/ +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +{ + if (Machine == IMAGE_FILE_MACHINE_RISCV64) { + return TRUE; + } + + return FALSE; +} + +/** + Performs an Itanium-based specific re-relocation fixup and is a no-op on other + instruction sets. This is used to re-relocated the image into the EFI virtual + space for runtime calls. + + @param Reloc The pointer to the relocation record. + @param Fixup The pointer to the address to fix up. + @param FixupData The pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + return RETURN_UNSUPPORTED; +} diff --git a/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf new file mode 100644 index 000000000..e2e808dde --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf @@ -0,0 +1,40 @@ +## @file +# Instance of Performance Library with empty functions. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePerformanceLibNull + MODULE_UNI_FILE = BasePerformanceLibNull.uni + FILE_GUID = FC120ED3-40E1-46dc-8C9C-AAE3CA139ACF + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PerformanceLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PerformanceLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + PcdLib + DebugLib + + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni new file mode 100644 index 000000000..a3c865351 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Performance Library with empty functions. +// +// Instance of Performance Library with empty functions. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Performance Library with empty functions" + +#string STR_MODULE_DESCRIPTION #language en-US "Instance of Performance Library with empty functions." + diff --git a/roms/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c new file mode 100644 index 000000000..11763b0c3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c @@ -0,0 +1,355 @@ +/** @file + Base Performance Library which provides no service. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include +#include + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, and Module. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle The pointer to environment specific context used + to identify the component being measured. + @param Token The pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module The pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + @retval RETURN_DEVICE_ERROR A device error reading the time stamp. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + return RETURN_SUCCESS; +} + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + + @param Handle The pointer to environment specific context used + to identify the component being measured. + @param Token The pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module The pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + @retval RETURN_DEVICE_ERROR A device error reading the time stamp. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + return RETURN_SUCCESS; +} + +/** + Attempts to retrieve a performance measurement log entry from the performance measurement log. + It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx, + and then eliminate the Identifier. + + Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is + zero on entry, then an attempt is made to retrieve the first entry from the performance log, + and the key for the second entry in the log is returned. If the performance log is empty, + then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance + log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is + returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is + retrieved and an implementation specific non-zero key value that specifies the end of the performance + log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry + is retrieved and zero is returned. In the cases where a performance log entry can be returned, + the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp. + If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT(). + If Handle is NULL, then ASSERT(). + If Token is NULL, then ASSERT(). + If Module is NULL, then ASSERT(). + If StartTimeStamp is NULL, then ASSERT(). + If EndTimeStamp is NULL, then ASSERT(). + + @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve. + 0, then the first performance measurement log entry is retrieved. + On exit, the key of the next performance lof entry entry. + @param Handle The pointer to environment specific context used to identify the component + being measured. + @param Token The pointer to a Null-terminated ASCII string that identifies the component + being measured. + @param Module The pointer to a Null-terminated ASCII string that identifies the module + being measured. + @param StartTimeStamp The pointer to the 64-bit time stamp that was recorded when the measurement + was started. + @param EndTimeStamp The pointer to the 64-bit time stamp that was recorded when the measurement + was ended. + + @return The key for the next performance log entry (in general case). + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + IN UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ) +{ + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + + return 0; +} + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, Module and Identifier. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + @param Identifier 32-bit identifier. If the value is 0, the created record + is same as the one created by StartPerformanceMeasurement. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + @retval RETURN_DEVICE_ERROR A device error reading the time stamp. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurementEx ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp, + IN UINT32 Identifier + ) +{ + return RETURN_SUCCESS; +} + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, Module and Identifier. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + @param Identifier 32-bit identifier. If the value is 0, the found record + is same as the one found by EndPerformanceMeasurement. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + @retval RETURN_DEVICE_ERROR A device error reading the time stamp. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurementEx ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp, + IN UINT32 Identifier + ) +{ + return RETURN_SUCCESS; +} + +/** + Attempts to retrieve a performance measurement log entry from the performance measurement log. + It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement, + and then assign the Identifier with 0. + + Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is + zero on entry, then an attempt is made to retrieve the first entry from the performance log, + and the key for the second entry in the log is returned. If the performance log is empty, + then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance + log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is + returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is + retrieved and an implementation specific non-zero key value that specifies the end of the performance + log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry + is retrieved and zero is returned. In the cases where a performance log entry can be returned, + the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier. + If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT(). + If Handle is NULL, then ASSERT(). + If Token is NULL, then ASSERT(). + If Module is NULL, then ASSERT(). + If StartTimeStamp is NULL, then ASSERT(). + If EndTimeStamp is NULL, then ASSERT(). + If Identifier is NULL, then ASSERT(). + + @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve. + 0, then the first performance measurement log entry is retrieved. + On exit, the key of the next performance lof entry entry. + @param Handle Pointer to environment specific context used to identify the component + being measured. + @param Token Pointer to a Null-terminated ASCII string that identifies the component + being measured. + @param Module Pointer to a Null-terminated ASCII string that identifies the module + being measured. + @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement + was started. + @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement + was ended. + @param Identifier Pointer to the 32-bit identifier that was recorded. + + @return The key for the next performance log entry (in general case). + +**/ +UINTN +EFIAPI +GetPerformanceMeasurementEx ( + IN UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp, + OUT UINT32 *Identifier + ) +{ + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + ASSERT (Identifier != NULL); + + return 0; +} + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); +} + +/** + Create performance record with event description and a timestamp. + + @param CallerIdentifier - Image handle or pointer to caller ID GUID + @param Guid - Pointer to a GUID + @param String - Pointer to a string describing the measurement + @param Address - Pointer to a location in memory relevant to the measurement + @param Identifier - Performance identifier describing the type of measurement + + @retval RETURN_SUCCESS - Successfully created performance record + @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records + @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL + pointer or invalid PerfId + +**/ +RETURN_STATUS +EFIAPI +LogPerformanceMeasurement ( + IN CONST VOID *CallerIdentifier,OPTIONAL + IN CONST VOID *Guid, OPTIONAL + IN CONST CHAR8 *String, OPTIONAL + IN UINT64 Address, OPTIONAL + IN UINT32 Identifier + ) +{ + return RETURN_SUCCESS; +} + +/** + Check whether the specified performance measurement can be logged. + + This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set + and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set. + + @param Type - Type of the performance measurement entry. + + @retval TRUE The performance measurement can be logged. + @retval FALSE The performance measurement can NOT be logged. + +**/ +BOOLEAN +EFIAPI +LogPerformanceMeasurementEnabled ( + IN CONST UINTN Type + ) +{ + // + // When Performance measurement is enabled and the type is not filtered, the performance can be logged. + // + if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) { + return TRUE; + } + return FALSE; +} diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf new file mode 100644 index 000000000..507924781 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf @@ -0,0 +1,45 @@ +## @file +# Instance of Post Code Library based on Debug Library. +# +# Post Code Library that uses DebugLib service to send PostCode. +# It layers on top of a Debug Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePostCodeLibDebug + MODULE_UNI_FILE = BasePostCodeLibDebug.uni + FILE_GUID = 19e3bbba-beb1-43e8-b32d-9acbb22c7639 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PostCodeLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + PostCode.c + + +[Packages] + MdePkg/MdePkg.dec + + + +[LibraryClasses] + PcdLib + DebugLib + + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni new file mode 100644 index 000000000..867b9390a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Post Code Library based on Debug Library. +// +// Post Code Library that uses DebugLib service to send PostCode. +// It layers on top of a Debug Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Post Code Library based on Debug Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Post Code Library that uses the DebugLib service to send PostCode. It layers on top of a Debug Library instance." + diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c new file mode 100644 index 000000000..b9254fa33 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c @@ -0,0 +1,121 @@ +/** @file + The instance of Post Code Library that layers on top of a Debug Library instance. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Post Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + DEBUG((EFI_D_INFO, "POST %08x\n", Value)); + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Post + Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description The pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + DEBUG((EFI_D_INFO, "POST %08x - %s\n", Value, Description)); + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeDescriptionEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf new file mode 100644 index 000000000..d1c01e773 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf @@ -0,0 +1,43 @@ +## @file +# Instance of Post Code Library using I/O port 0x80. +# +# Post Code Library that writes post code values to I/O port 0x80. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePostCodeLibPort80 + MODULE_UNI_FILE = BasePostCodeLibPort80.uni + FILE_GUID = b6e9a733-eb75-41b6-b30c-009bcf3801c8 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PostCodeLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PostCode.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + IoLib + PcdLib + DebugLib + + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdPort80DataWidth ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni new file mode 100644 index 000000000..e22b7fc82 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Post Code Library using I/O port 0x80. +// +// Post Code Library that writes post code values to I/O port 0x80. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Post Code Library using I/O port 0x80" + +#string STR_MODULE_DESCRIPTION #language en-US "Post Code Library that writes post code values to I/O port 0x80." + diff --git a/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c new file mode 100644 index 000000000..bcba4a733 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c @@ -0,0 +1,139 @@ +/** @file + Post Code Library instance that writes post code values to I/O port 0x80. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Post Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + switch (PcdGet8 (PcdPort80DataWidth)) { + case 8: + IoWrite8 (0x80, (UINT8)(Value)); + break; + case 16: + IoWrite16 (0x80, (UINT16)(Value)); + break; + case 32: + IoWrite32 (0x80, Value); + break; + default: + // + // Assert on the invalid data width + // + ASSERT (FALSE); + break; + } + + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Post + Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description The pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + PostCode (Value); + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeDescriptionEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} diff --git a/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf b/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf new file mode 100644 index 000000000..4f99326dd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf @@ -0,0 +1,45 @@ +## @file +# Print Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePrintLib + MODULE_UNI_FILE = BasePrintLib.uni + FILE_GUID = a86fbfca-0183-4eeb-aa8a-762e3b7da1f3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PrintLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + PrintLibInternal.h + PrintLibInternal.c + PrintLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + BaseLib + PcdLib + + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## SOMETIMES_CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni b/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni new file mode 100644 index 000000000..c02ee7008 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Print Library implementation. +// +// Print Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Print Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "Print Library implementation." + diff --git a/roms/edk2/MdePkg/Library/BasePrintLib/PrintLib.c b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLib.c new file mode 100644 index 000000000..af771652e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLib.c @@ -0,0 +1,955 @@ +/** @file + Base Print Library instance implementation. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PrintLibInternal.h" + +// +// Declare a VA_LIST global variable that is used in calls to BasePrintLibSPrintMarker() +// when the BASE_LIST parameter is valid and the VA_LIST parameter is ignored. +// A NULL VA_LIST can not be passed into BasePrintLibSPrintMarker() because some +// compilers define VA_LIST to be a structure. +// +VA_LIST gNullVaList; + +#define ASSERT_UNICODE_BUFFER(Buffer) ASSERT ((((UINTN) (Buffer)) & 0x01) == 0) + +/** + Produces a Null-terminated Unicode string in an output buffer based on + a Null-terminated Unicode format string and a VA_LIST argument list. + + This function is similar as vsnprintf_s defined in C11. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on the + contents of the format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then the output buffer is unmodified and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param Marker VA_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeVSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (StartOfBuffer); + ASSERT_UNICODE_BUFFER (FormatString); + return BasePrintLibSPrintMarker ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker, NULL); +} + +/** + Produces a Null-terminated Unicode string in an output buffer based on + a Null-terminated Unicode format string and a BASE_LIST argument list. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on the + contents of the format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then the output buffer is unmodified and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param Marker BASE_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeBSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN BASE_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (StartOfBuffer); + ASSERT_UNICODE_BUFFER (FormatString); + return BasePrintLibSPrintMarker ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, gNullVaList, Marker); +} + +/** + Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated + Unicode format string and variable argument list. + + This function is similar as snprintf_s defined in C11. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list based on the contents of the format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then the output buffer is unmodified and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param ... Variable argument list whose contents are accessed based on the + format string specified by FormatString. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ) +{ + VA_LIST Marker; + UINTN NumberOfPrinted; + + VA_START (Marker, FormatString); + NumberOfPrinted = UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return NumberOfPrinted; +} + +/** + Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated + ASCII format string and a VA_LIST argument list. + + This function is similar as vsnprintf_s defined in C11. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on the + contents of the format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param Marker VA_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeVSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (StartOfBuffer); + return BasePrintLibSPrintMarker ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE, FormatString, Marker, NULL); +} + +/** + Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated + ASCII format string and a BASE_LIST argument list. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on the + contents of the format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param Marker BASE_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeBSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN BASE_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (StartOfBuffer); + return BasePrintLibSPrintMarker ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE, FormatString, gNullVaList, Marker); +} + +/** + Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated + ASCII format string and variable argument list. + + This function is similar as snprintf_s defined in C11. + + Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer + and BufferSize. + The Unicode string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list based on the contents of the + format string. + The number of Unicode characters in the produced output buffer is returned not including + the Null-terminator. + + If StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 1 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and BufferSize > + (PcdMaximumUnicodeStringLength * sizeof (CHAR16) + 1), then ASSERT(). Also, the output + buffer is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + Unicode string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param ... Variable argument list whose contents are accessed based on the + format string specified by FormatString. + + @return The number of Unicode characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + UINTN NumberOfPrinted; + + VA_START (Marker, FormatString); + NumberOfPrinted = UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return NumberOfPrinted; +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is deprecated for security reason. + + Converts a decimal value to a Null-terminated Unicode string. + + Converts the decimal number specified by Value to a Null-terminated Unicode + string specified by Buffer containing at most Width characters. No padding of spaces + is ever performed. If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + The number of Unicode characters in Buffer is returned not including the Null-terminator. + If the conversion contains more than Width characters, then only the first + Width characters are returned, and the total number of characters + required to perform the conversion is returned. + Additional conversion parameters are specified in Flags. + + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas + are inserted every 3rd digit starting from the right. + If RADIX_HEX is set in Flags, then the output buffer will be + formatted in hexadecimal format. + If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the Null-terminator + add up to Width characters. + If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If unsupported bits are set in Flags, then ASSERT(). + If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT(). + If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT() + + @param Buffer The pointer to the output buffer for the produced Null-terminated + Unicode string. + @param Flags The bitmask of flags that specify left justification, zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of Unicode characters to place in Buffer, not including + the Null-terminator. + + @return The number of Unicode characters in Buffer not including the Null-terminator. + +**/ +UINTN +EFIAPI +UnicodeValueToString ( + IN OUT CHAR16 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + ASSERT_UNICODE_BUFFER(Buffer); + return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2); +} + +#endif + +/** + Converts a decimal value to a Null-terminated Unicode string. + + Converts the decimal number specified by Value to a Null-terminated Unicode + string specified by Buffer containing at most Width characters. No padding of + spaces is ever performed. If Width is 0 then a width of + MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more than + Width characters, then only the first Width characters are placed in Buffer. + Additional conversion parameters are specified in Flags. + + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and + commas are inserted every 3rd digit starting from the right. + If RADIX_HEX is set in Flags, then the output buffer will be formatted in + hexadecimal format. + If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in + Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, then + Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the + Null-terminator add up to Width characters. + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + @param Buffer The pointer to the output buffer for the produced + Null-terminated Unicode string. + @param BufferSize The size of Buffer in bytes, including the + Null-terminator. + @param Flags The bitmask of flags that specify left justification, + zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of Unicode characters to place in + Buffer, not including the Null-terminator. + + @retval RETURN_SUCCESS The decimal value is converted. + @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted + value. + @retval RETURN_INVALID_PARAMETER If Buffer is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and BufferSize is greater than + (PcdMaximumUnicodeStringLength * + sizeof (CHAR16) + 1). + If unsupported bits are set in Flags. + If both COMMA_TYPE and RADIX_HEX are set in + Flags. + If Width >= MAXIMUM_VALUE_CHARACTERS. + +**/ +RETURN_STATUS +EFIAPI +UnicodeValueToStringS ( + IN OUT CHAR16 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + ASSERT_UNICODE_BUFFER(Buffer); + return BasePrintLibConvertValueToStringS ((CHAR8 *)Buffer, BufferSize, Flags, Value, Width, 2); +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + ASCII format string and a VA_LIST argument list. + + This function is similar as vsnprintf_s defined in C11. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on + the contents of the format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param Marker VA_LIST marker for the variable argument list. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiVSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, 0, FormatString, Marker, NULL); +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + ASCII format string and a BASE_LIST argument list. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on + the contents of the format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param Marker BASE_LIST marker for the variable argument list. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiBSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN BASE_LIST Marker + ) +{ + return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, 0, FormatString, gNullVaList, Marker); +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + ASCII format string and variable argument list. + + This function is similar as snprintf_s defined in C11. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list based on the contents of the + format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than + PcdMaximumAsciiStringLength Ascii characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated ASCII format string. + @param ... Variable argument list whose contents are accessed based on the + format string specified by FormatString. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + UINTN NumberOfPrinted; + + VA_START (Marker, FormatString); + NumberOfPrinted = AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return NumberOfPrinted; +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + Unicode format string and a VA_LIST argument list. + + This function is similar as vsnprintf_s defined in C11. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on + the contents of the format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param Marker VA_LIST marker for the variable argument list. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiVSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (FormatString); + return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, Marker, NULL); +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + Unicode format string and a BASE_LIST argument list. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list specified by Marker based on + the contents of the format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param Marker BASE_LIST marker for the variable argument list. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiBSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN BASE_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (FormatString); + return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, gNullVaList, Marker); +} + +/** + Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated + Unicode format string and variable argument list. + + This function is similar as snprintf_s defined in C11. + + Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer + and BufferSize. + The ASCII string is produced by parsing the format string specified by FormatString. + Arguments are pulled from the variable argument list based on the contents of the + format string. + The number of ASCII characters in the produced output buffer is returned not including + the Null-terminator. + + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If BufferSize > 0 and FormatString is NULL, then ASSERT(). Also, the output buffer is + unmodified and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and BufferSize > + (PcdMaximumAsciiStringLength * sizeof (CHAR8)), then ASSERT(). Also, the output buffer + is unmodified and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then + ASSERT(). Also, the output buffer is unmodified and 0 is returned. + + If BufferSize is 0, then no output buffer is produced and 0 is returned. + + @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated + ASCII string. + @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer. + @param FormatString A Null-terminated Unicode format string. + @param ... Variable argument list whose contents are accessed based on the + format string specified by FormatString. + + @return The number of ASCII characters in the produced output buffer not including the + Null-terminator. + +**/ +UINTN +EFIAPI +AsciiSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ) +{ + VA_LIST Marker; + UINTN NumberOfPrinted; + + VA_START (Marker, FormatString); + NumberOfPrinted = AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return NumberOfPrinted; +} + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is deprecated for security reason. + + Converts a decimal value to a Null-terminated ASCII string. + + Converts the decimal number specified by Value to a Null-terminated ASCII string + specified by Buffer containing at most Width characters. No padding of spaces + is ever performed. + If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + The number of ASCII characters in Buffer is returned not including the Null-terminator. + If the conversion contains more than Width characters, then only the first Width + characters are returned, and the total number of characters required to perform + the conversion is returned. + Additional conversion parameters are specified in Flags. + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas + are inserted every 3rd digit starting from the right. + If RADIX_HEX is set in Flags, then the output buffer will be + formatted in hexadecimal format. + If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the Null-terminator + add up to Width characters. + + If Buffer is NULL, then ASSERT(). + If unsupported bits are set in Flags, then ASSERT(). + If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT(). + If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT() + + @param Buffer The pointer to the output buffer for the produced Null-terminated + ASCII string. + @param Flags The bitmask of flags that specify left justification, zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of ASCII characters to place in Buffer, not including + the Null-terminator. + + @return The number of ASCII characters in Buffer not including the Null-terminator. + +**/ +UINTN +EFIAPI +AsciiValueToString ( + OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + return BasePrintLibConvertValueToString (Buffer, Flags, Value, Width, 1); +} + +#endif + +/** + Converts a decimal value to a Null-terminated Ascii string. + + Converts the decimal number specified by Value to a Null-terminated Ascii + string specified by Buffer containing at most Width characters. No padding of + spaces is ever performed. If Width is 0 then a width of + MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more than + Width characters, then only the first Width characters are placed in Buffer. + Additional conversion parameters are specified in Flags. + + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and + commas are inserted every 3rd digit starting from the right. + If RADIX_HEX is set in Flags, then the output buffer will be formatted in + hexadecimal format. + If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in + Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, then + Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the + Null-terminator add up to Width characters. + + If an error would be returned, then the function will ASSERT(). + + @param Buffer The pointer to the output buffer for the produced + Null-terminated Ascii string. + @param BufferSize The size of Buffer in bytes, including the + Null-terminator. + @param Flags The bitmask of flags that specify left justification, + zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of Ascii characters to place in + Buffer, not including the Null-terminator. + + @retval RETURN_SUCCESS The decimal value is converted. + @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted + value. + @retval RETURN_INVALID_PARAMETER If Buffer is NULL. + If PcdMaximumAsciiStringLength is not + zero, and BufferSize is greater than + PcdMaximumAsciiStringLength. + If unsupported bits are set in Flags. + If both COMMA_TYPE and RADIX_HEX are set in + Flags. + If Width >= MAXIMUM_VALUE_CHARACTERS. + +**/ +RETURN_STATUS +EFIAPI +AsciiValueToStringS ( + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + return BasePrintLibConvertValueToStringS (Buffer, BufferSize, Flags, Value, Width, 1); +} + +/** + Returns the number of characters that would be produced by if the formatted + output were produced not including the Null-terminator. + + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + If FormatString is NULL, then ASSERT() and 0 is returned. + If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more + than PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT() and 0 is returned. + + @param[in] FormatString A Null-terminated Unicode format string. + @param[in] Marker VA_LIST marker for the variable argument list. + + @return The number of characters that would be produced, not including the + Null-terminator. +**/ +UINTN +EFIAPI +SPrintLength ( + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + ASSERT_UNICODE_BUFFER (FormatString); + return BasePrintLibSPrintMarker (NULL, 0, FORMAT_UNICODE | OUTPUT_UNICODE | COUNT_ONLY_NO_PRINT, (CHAR8 *)FormatString, Marker, NULL); +} + +/** + Returns the number of characters that would be produced by if the formatted + output were produced not including the Null-terminator. + + If FormatString is NULL, then ASSERT() and 0 is returned. + If PcdMaximumAsciiStringLength is not zero, and FormatString contains more + than PcdMaximumAsciiStringLength Ascii characters not including the + Null-terminator, then ASSERT() and 0 is returned. + + @param[in] FormatString A Null-terminated ASCII format string. + @param[in] Marker VA_LIST marker for the variable argument list. + + @return The number of characters that would be produced, not including the + Null-terminator. +**/ +UINTN +EFIAPI +SPrintLengthAsciiFormat ( + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibSPrintMarker (NULL, 0, OUTPUT_UNICODE | COUNT_ONLY_NO_PRINT, (CHAR8 *)FormatString, Marker, NULL); +} diff --git a/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c new file mode 100644 index 000000000..50c6e8559 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c @@ -0,0 +1,1272 @@ +/** @file + Print Library internal worker functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PrintLibInternal.h" + +#define WARNING_STATUS_NUMBER 5 +#define ERROR_STATUS_NUMBER 33 + +// +// Safe print checks +// +#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength)) +#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength)) + +#define SAFE_PRINT_CONSTRAINT_CHECK(Expression, RetVal) \ + do { \ + ASSERT (Expression); \ + if (!(Expression)) { \ + return RetVal; \ + } \ + } while (FALSE) + +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +// +// Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString[][24+1] = { + "Success", // RETURN_SUCCESS = 0 + "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1 + "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2 + "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3 + "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4 + "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5 +}; + +// +// Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString[][20+1] = { + "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT + "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT + "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT + "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT + "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT + "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT + "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT + "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT + "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT + "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT + "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT + "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT + "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT + "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT + "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT + "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT + "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT + "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT + "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT + "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT + "Aborted", // RETURN_ABORTED = 21 | MAX_BIT + "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT + "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT + "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT + "Incompatible Version", // RETURN_INCOMPATIBLE_VERSION = 25 | MAX_BIT + "Security Violation", // RETURN_SECURITY_VIOLATION = 26 | MAX_BIT + "CRC Error", // RETURN_CRC_ERROR = 27 | MAX_BIT + "End of Media", // RETURN_END_OF_MEDIA = 28 | MAX_BIT + "Reserved (29)", // RESERVED = 29 | MAX_BIT + "Reserved (30)", // RESERVED = 30 | MAX_BIT + "End of File", // RETURN_END_OF_FILE = 31 | MAX_BIT + "Invalid Language", // RETURN_INVALID_LANGUAGE = 32 | MAX_BIT + "Compromised Data" // RETURN_COMPROMISED_DATA = 33 | MAX_BIT +}; + + +/** + Internal function that places the character into the Buffer. + + Internal function that places ASCII or Unicode character into the Buffer. + + @param Buffer The buffer to place the Unicode or ASCII string. + @param EndBuffer The end of the input Buffer. No characters will be + placed after that. + @param Length The count of character to be placed into Buffer. + (Negative value indicates no buffer fill.) + @param Character The character to be placed into Buffer. + @param Increment The character increment in Buffer. + + @return Buffer. + +**/ +CHAR8 * +BasePrintLibFillBuffer ( + OUT CHAR8 *Buffer, + IN CHAR8 *EndBuffer, + IN INTN Length, + IN UINTN Character, + IN INTN Increment + ) +{ + INTN Index; + + for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) { + *Buffer = (CHAR8) Character; + if (Increment != 1) { + *(Buffer + 1) = (CHAR8)(Character >> 8); + } + Buffer += Increment; + } + + return Buffer; +} + +/** + Internal function that convert a number to a string in Buffer. + + Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer. + + @param Buffer Location to place the ASCII string of Value. + @param Value The value to convert to a Decimal or Hexadecimal string in Buffer. + @param Radix Radix of the value + + @return A pointer to the end of buffer filled with ASCII string. + +**/ +CHAR8 * +BasePrintLibValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Radix + ) +{ + UINT32 Remainder; + + // + // Loop to convert one digit at a time in reverse order + // + *Buffer = 0; + do { + Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder); + *(++Buffer) = mHexStr[Remainder]; + } while (Value != 0); + + // + // Return pointer of the end of filled buffer. + // + return Buffer; +} + +/** + Internal function that converts a decimal value to a Null-terminated string. + + Converts the decimal number specified by Value to a Null-terminated + string specified by Buffer containing at most Width characters. + If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + The total number of characters placed in Buffer is returned. + If the conversion contains more than Width characters, then only the first + Width characters are returned, and the total number of characters + required to perform the conversion is returned. + Additional conversion parameters are specified in Flags. + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas + are inserted every 3rd digit starting from the right. + If Value is < 0, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the Null-terminator + add up to Width characters. + + If Buffer is NULL, then ASSERT(). + If unsupported bits are set in Flags, then ASSERT(). + If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT() + + @param Buffer The pointer to the output buffer for the produced Null-terminated + string. + @param Flags The bitmask of flags that specify left justification, zero pad, + and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of characters to place in Buffer, not including + the Null-terminator. + @param Increment The character increment in Buffer. + + @return Total number of characters required to perform the conversion. + +**/ +UINTN +BasePrintLibConvertValueToString ( + IN OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width, + IN UINTN Increment + ) +{ + CHAR8 *OriginalBuffer; + CHAR8 *EndBuffer; + CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS]; + CHAR8 *ValueBufferPtr; + UINTN Count; + UINTN Digits; + UINTN Index; + UINTN Radix; + + // + // Make sure Buffer is not NULL and Width < MAXIMUM + // + ASSERT (Buffer != NULL); + ASSERT (Width < MAXIMUM_VALUE_CHARACTERS); + // + // Make sure Flags can only contain supported bits. + // + ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0); + + // + // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT () + // + ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0)); + + OriginalBuffer = Buffer; + + // + // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored. + // + if (Width == 0 || (Flags & COMMA_TYPE) != 0) { + Flags &= ~((UINTN) PREFIX_ZERO); + } + // + // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + // + if (Width == 0) { + Width = MAXIMUM_VALUE_CHARACTERS - 1; + } + // + // Set the tag for the end of the input Buffer. + // + EndBuffer = Buffer + Width * Increment; + + // + // Convert decimal negative + // + if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) { + Value = -Value; + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment); + Width--; + } + + // + // Count the length of the value string. + // + Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16; + ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix); + Count = ValueBufferPtr - ValueBuffer; + + // + // Append Zero + // + if ((Flags & PREFIX_ZERO) != 0) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment); + } + + // + // Print Comma type for every 3 characters + // + Digits = Count % 3; + if (Digits != 0) { + Digits = 3 - Digits; + } + for (Index = 0; Index < Count; Index++) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment); + if ((Flags & COMMA_TYPE) != 0) { + Digits++; + if (Digits == 3) { + Digits = 0; + if ((Index + 1) < Count) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment); + } + } + } + } + + // + // Print Null-terminator + // + BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment); + + return ((Buffer - OriginalBuffer) / Increment); +} + +/** + Internal function that converts a decimal value to a Null-terminated string. + + Converts the decimal number specified by Value to a Null-terminated string + specified by Buffer containing at most Width characters. If Width is 0 then a + width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more + than Width characters, then only the first Width characters are placed in + Buffer. Additional conversion parameters are specified in Flags. + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and + commas are inserted every 3rd digit starting from the right. + If Value is < 0, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional + '-' sign character, '0' characters, digit characters for Value, and the + Null-terminator add up to Width characters. + + If an error would be returned, the function will ASSERT(). + + @param Buffer The pointer to the output buffer for the produced + Null-terminated string. + @param BufferSize The size of Buffer in bytes, including the + Null-terminator. + @param Flags The bitmask of flags that specify left justification, + zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of characters to place in Buffer, + not including the Null-terminator. + @param Increment The character increment in Buffer. + + @retval RETURN_SUCCESS The decimal value is converted. + @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted + value. + @retval RETURN_INVALID_PARAMETER If Buffer is NULL. + If Increment is 1 and + PcdMaximumAsciiStringLength is not zero, + BufferSize is greater than + PcdMaximumAsciiStringLength. + If Increment is not 1 and + PcdMaximumUnicodeStringLength is not zero, + BufferSize is greater than + (PcdMaximumUnicodeStringLength * + sizeof (CHAR16) + 1). + If unsupported bits are set in Flags. + If both COMMA_TYPE and RADIX_HEX are set in + Flags. + If Width >= MAXIMUM_VALUE_CHARACTERS. + +**/ +RETURN_STATUS +BasePrintLibConvertValueToStringS ( + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width, + IN UINTN Increment + ) +{ + CHAR8 *EndBuffer; + CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS]; + CHAR8 *ValueBufferPtr; + UINTN Count; + UINTN Digits; + UINTN Index; + UINTN Radix; + + // + // 1. Buffer shall not be a null pointer. + // + SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for + // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for + // Ascii output string. + // + if (Increment == 1) { + // + // Ascii output string + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + } else { + // + // Unicode output string + // + if (RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX * sizeof (CHAR16) + 1), RETURN_INVALID_PARAMETER); + } + } + + // + // 3. Flags shall be set properly. + // + SAFE_PRINT_CONSTRAINT_CHECK (((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0), RETURN_INVALID_PARAMETER); + SAFE_PRINT_CONSTRAINT_CHECK ((((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0)), RETURN_INVALID_PARAMETER); + + // + // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS. + // + SAFE_PRINT_CONSTRAINT_CHECK ((Width < MAXIMUM_VALUE_CHARACTERS), RETURN_INVALID_PARAMETER); + + // + // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored. + // + if (Width == 0 || (Flags & COMMA_TYPE) != 0) { + Flags &= ~((UINTN) PREFIX_ZERO); + } + // + // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + // + if (Width == 0) { + Width = MAXIMUM_VALUE_CHARACTERS - 1; + } + + // + // Count the characters of the output string. + // + Count = 0; + Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16; + + if ((Flags & PREFIX_ZERO) != 0) { + Count = Width; + } else { + if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) { + Count++; // minus sign + ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, -Value, Radix); + } else { + ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix); + } + Digits = ValueBufferPtr - ValueBuffer; + Count += Digits; + + if ((Flags & COMMA_TYPE) != 0) { + Count += (Digits - 1) / 3; // commas + } + } + + Width = MIN (Count, Width); + + // + // 5. BufferSize shall be large enough to hold the converted string. + // + SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize >= (Width + 1) * Increment), RETURN_BUFFER_TOO_SMALL); + + // + // Set the tag for the end of the input Buffer. + // + EndBuffer = Buffer + Width * Increment; + + // + // Convert decimal negative + // + if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) { + Value = -Value; + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment); + Width--; + } + + // + // Count the length of the value string. + // + ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix); + Count = ValueBufferPtr - ValueBuffer; + + // + // Append Zero + // + if ((Flags & PREFIX_ZERO) != 0) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment); + } + + // + // Print Comma type for every 3 characters + // + Digits = Count % 3; + if (Digits != 0) { + Digits = 3 - Digits; + } + for (Index = 0; Index < Count; Index++) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment); + if ((Flags & COMMA_TYPE) != 0) { + Digits++; + if (Digits == 3) { + Digits = 0; + if ((Index + 1) < Count) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment); + } + } + } + } + + // + // Print Null-terminator + // + BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment); + + return RETURN_SUCCESS; +} + +/** + Worker function that produces a Null-terminated string in an output buffer + based on a Null-terminated format string and a VA_LIST argument list. + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this routine allows the nesting of Vararg routines. Thus + this is the main print working routine. + + If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all. + + @param[out] Buffer The character buffer to print the results of the + parsing of Format into. + @param[in] BufferSize The maximum number of characters to put into + buffer. + @param[in] Flags Initial flags value. + Can only have FORMAT_UNICODE, OUTPUT_UNICODE, + and COUNT_ONLY_NO_PRINT set. + @param[in] Format A Null-terminated format string. + @param[in] VaListMarker VA_LIST style variable argument list consumed by + processing Format. + @param[in] BaseListMarker BASE_LIST style variable argument list consumed + by processing Format. + + @return The number of characters printed not including the Null-terminator. + If COUNT_ONLY_NO_PRINT was set returns the same, but without any + modification to Buffer. + +**/ +UINTN +BasePrintLibSPrintMarker ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, OPTIONAL + IN BASE_LIST BaseListMarker OPTIONAL + ) +{ + CHAR8 *OriginalBuffer; + CHAR8 *EndBuffer; + CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS]; + UINT32 BytesPerOutputCharacter; + UINTN BytesPerFormatCharacter; + UINTN FormatMask; + UINTN FormatCharacter; + UINTN Width; + UINTN Precision; + INT64 Value; + CONST CHAR8 *ArgumentString; + UINTN Character; + GUID *TmpGuid; + TIME *TmpTime; + UINTN Count; + UINTN ArgumentMask; + INTN BytesPerArgumentCharacter; + UINTN ArgumentCharacter; + BOOLEAN Done; + UINTN Index; + CHAR8 Prefix; + BOOLEAN ZeroPad; + BOOLEAN Comma; + UINTN Digits; + UINTN Radix; + RETURN_STATUS Status; + UINT32 GuidData1; + UINT16 GuidData2; + UINT16 GuidData3; + UINTN LengthToReturn; + + // + // If you change this code be sure to match the 2 versions of this function. + // Nearly identical logic is found in the BasePrintLib and + // DxePrintLibPrint2Protocol (both PrintLib instances). + // + + // + // 1. Buffer shall not be a null pointer when both BufferSize > 0 and + // COUNT_ONLY_NO_PRINT is not set in Flags. + // + if ((BufferSize > 0) && ((Flags & COUNT_ONLY_NO_PRINT) == 0)) { + SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), 0); + } + + // + // 2. Format shall not be a null pointer when BufferSize > 0 or when + // COUNT_ONLY_NO_PRINT is set in Flags. + // + if ((BufferSize > 0) || ((Flags & COUNT_ONLY_NO_PRINT) != 0)) { + SAFE_PRINT_CONSTRAINT_CHECK ((Format != NULL), 0); + } + + // + // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or + // ASCII_RSIZE_MAX for Ascii output. + // + if ((Flags & OUTPUT_UNICODE) != 0) { + if (RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX), 0); + } + BytesPerOutputCharacter = 2; + } else { + if (ASCII_RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), 0); + } + BytesPerOutputCharacter = 1; + } + + // + // 4. Format shall not contain more than RSIZE_MAX Unicode characters or + // ASCII_RSIZE_MAX Ascii characters. + // + if ((Flags & FORMAT_UNICODE) != 0) { + if (RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16 *)Format, RSIZE_MAX + 1) <= RSIZE_MAX), 0); + } + BytesPerFormatCharacter = 2; + FormatMask = 0xffff; + } else { + if (ASCII_RSIZE_MAX != 0) { + SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), 0); + } + BytesPerFormatCharacter = 1; + FormatMask = 0xff; + } + + if ((Flags & COUNT_ONLY_NO_PRINT) != 0) { + if (BufferSize == 0) { + Buffer = NULL; + } + } else { + // + // We can run without a Buffer for counting only. + // + if (BufferSize == 0) { + return 0; + } + } + + LengthToReturn = 0; + EndBuffer = NULL; + OriginalBuffer = NULL; + + // + // Reserve space for the Null terminator. + // + if (Buffer != NULL) { + BufferSize--; + OriginalBuffer = Buffer; + + // + // Set the tag for the end of the input Buffer. + // + EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter; + } + + // + // Get the first character from the format string + // + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + + // + // Loop until the end of the format string is reached or the output buffer is full + // + while (FormatCharacter != 0) { + if ((Buffer != NULL) && (Buffer >= EndBuffer)) { + break; + } + // + // Clear all the flag bits except those that may have been passed in + // + Flags &= (UINTN) (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT); + + // + // Set the default width to zero, and the default precision to 1 + // + Width = 0; + Precision = 1; + Prefix = 0; + Comma = FALSE; + ZeroPad = FALSE; + Count = 0; + Digits = 0; + + switch (FormatCharacter) { + case '%': + // + // Parse Flags and Width + // + for (Done = FALSE; !Done; ) { + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + switch (FormatCharacter) { + case '.': + Flags |= PRECISION; + break; + case '-': + Flags |= LEFT_JUSTIFY; + break; + case '+': + Flags |= PREFIX_SIGN; + break; + case ' ': + Flags |= PREFIX_BLANK; + break; + case ',': + Flags |= COMMA_TYPE; + break; + case 'L': + case 'l': + Flags |= LONG_TYPE; + break; + case '*': + if ((Flags & PRECISION) == 0) { + Flags |= PAD_TO_WIDTH; + if (BaseListMarker == NULL) { + Width = VA_ARG (VaListMarker, UINTN); + } else { + Width = BASE_ARG (BaseListMarker, UINTN); + } + } else { + if (BaseListMarker == NULL) { + Precision = VA_ARG (VaListMarker, UINTN); + } else { + Precision = BASE_ARG (BaseListMarker, UINTN); + } + } + break; + case '0': + if ((Flags & PRECISION) == 0) { + Flags |= PREFIX_ZERO; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){ + Count = (Count * 10) + FormatCharacter - '0'; + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + } + Format -= BytesPerFormatCharacter; + if ((Flags & PRECISION) == 0) { + Flags |= PAD_TO_WIDTH; + Width = Count; + } else { + Precision = Count; + } + break; + + case '\0': + // + // Make no output if Format string terminates unexpectedly when + // looking up for flag, width, precision and type. + // + Format -= BytesPerFormatCharacter; + Precision = 0; + // + // break skipped on purpose. + // + default: + Done = TRUE; + break; + } + } + + // + // Handle each argument type + // + switch (FormatCharacter) { + case 'p': + // + // Flag space, +, 0, L & l are invalid for type p. + // + Flags &= ~((UINTN) (PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE)); + if (sizeof (VOID *) > 4) { + Flags |= LONG_TYPE; + } + // + // break skipped on purpose + // + case 'X': + Flags |= PREFIX_ZERO; + // + // break skipped on purpose + // + case 'x': + Flags |= RADIX_HEX; + // + // break skipped on purpose + // + case 'u': + if ((Flags & RADIX_HEX) == 0) { + Flags &= ~((UINTN) (PREFIX_SIGN)); + Flags |= UNSIGNED_TYPE; + } + // + // break skipped on purpose + // + case 'd': + if ((Flags & LONG_TYPE) == 0) { + // + // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int". + // This assumption is made so the format string definition is compatible with the ANSI C + // Specification for formatted strings. It is recommended that the Base Types be used + // everywhere, but in this one case, compliance with ANSI C is more important, and + // provides an implementation that is compatible with that largest possible set of CPU + // architectures. This is why the type "int" is used in this one case. + // + if (BaseListMarker == NULL) { + Value = VA_ARG (VaListMarker, int); + } else { + Value = BASE_ARG (BaseListMarker, int); + } + } else { + if (BaseListMarker == NULL) { + Value = VA_ARG (VaListMarker, INT64); + } else { + Value = BASE_ARG (BaseListMarker, INT64); + } + } + if ((Flags & PREFIX_BLANK) != 0) { + Prefix = ' '; + } + if ((Flags & PREFIX_SIGN) != 0) { + Prefix = '+'; + } + if ((Flags & COMMA_TYPE) != 0) { + Comma = TRUE; + } + if ((Flags & RADIX_HEX) == 0) { + Radix = 10; + if (Comma) { + Flags &= ~((UINTN) PREFIX_ZERO); + Precision = 1; + } + if (Value < 0 && (Flags & UNSIGNED_TYPE) == 0) { + Flags |= PREFIX_SIGN; + Prefix = '-'; + Value = -Value; + } else if ((Flags & UNSIGNED_TYPE) != 0 && (Flags & LONG_TYPE) == 0) { + // + // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int". + // This assumption is made so the format string definition is compatible with the ANSI C + // Specification for formatted strings. It is recommended that the Base Types be used + // everywhere, but in this one case, compliance with ANSI C is more important, and + // provides an implementation that is compatible with that largest possible set of CPU + // architectures. This is why the type "unsigned int" is used in this one case. + // + Value = (unsigned int)Value; + } + } else { + Radix = 16; + Comma = FALSE; + if ((Flags & LONG_TYPE) == 0 && Value < 0) { + // + // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int". + // This assumption is made so the format string definition is compatible with the ANSI C + // Specification for formatted strings. It is recommended that the Base Types be used + // everywhere, but in this one case, compliance with ANSI C is more important, and + // provides an implementation that is compatible with that largest possible set of CPU + // architectures. This is why the type "unsigned int" is used in this one case. + // + Value = (unsigned int)Value; + } + } + // + // Convert Value to a reversed string + // + Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer; + if (Value == 0 && Precision == 0) { + Count = 0; + } + ArgumentString = (CHAR8 *)ValueBuffer + Count; + + Digits = Count % 3; + if (Digits != 0) { + Digits = 3 - Digits; + } + if (Comma && Count != 0) { + Count += ((Count - 1) / 3); + } + if (Prefix != 0) { + Count++; + Precision++; + } + Flags |= ARGUMENT_REVERSED; + ZeroPad = TRUE; + if ((Flags & PREFIX_ZERO) != 0) { + if ((Flags & LEFT_JUSTIFY) == 0) { + if ((Flags & PAD_TO_WIDTH) != 0) { + if ((Flags & PRECISION) == 0) { + Precision = Width; + } + } + } + } + break; + + case 's': + case 'S': + Flags |= ARGUMENT_UNICODE; + // + // break skipped on purpose + // + case 'a': + if (BaseListMarker == NULL) { + ArgumentString = VA_ARG (VaListMarker, CHAR8 *); + } else { + ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *); + } + if (ArgumentString == NULL) { + Flags &= ~((UINTN) ARGUMENT_UNICODE); + ArgumentString = ""; + } + // + // Set the default precision for string to be zero if not specified. + // + if ((Flags & PRECISION) == 0) { + Precision = 0; + } + break; + + case 'c': + if (BaseListMarker == NULL) { + Character = VA_ARG (VaListMarker, UINTN) & 0xffff; + } else { + Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff; + } + ArgumentString = (CHAR8 *)&Character; + Flags |= ARGUMENT_UNICODE; + break; + + case 'g': + if (BaseListMarker == NULL) { + TmpGuid = VA_ARG (VaListMarker, GUID *); + } else { + TmpGuid = BASE_ARG (BaseListMarker, GUID *); + } + if (TmpGuid == NULL) { + ArgumentString = ""; + } else { + GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1)); + GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2)); + GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3)); + BasePrintLibSPrint ( + ValueBuffer, + MAXIMUM_VALUE_CHARACTERS, + 0, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + GuidData1, + GuidData2, + GuidData3, + TmpGuid->Data4[0], + TmpGuid->Data4[1], + TmpGuid->Data4[2], + TmpGuid->Data4[3], + TmpGuid->Data4[4], + TmpGuid->Data4[5], + TmpGuid->Data4[6], + TmpGuid->Data4[7] + ); + ArgumentString = ValueBuffer; + } + break; + + case 't': + if (BaseListMarker == NULL) { + TmpTime = VA_ARG (VaListMarker, TIME *); + } else { + TmpTime = BASE_ARG (BaseListMarker, TIME *); + } + if (TmpTime == NULL) { + ArgumentString = ""; + } else { + BasePrintLibSPrint ( + ValueBuffer, + MAXIMUM_VALUE_CHARACTERS, + 0, + "%02d/%02d/%04d %02d:%02d", + TmpTime->Month, + TmpTime->Day, + TmpTime->Year, + TmpTime->Hour, + TmpTime->Minute + ); + ArgumentString = ValueBuffer; + } + break; + + case 'r': + if (BaseListMarker == NULL) { + Status = VA_ARG (VaListMarker, RETURN_STATUS); + } else { + Status = BASE_ARG (BaseListMarker, RETURN_STATUS); + } + ArgumentString = ValueBuffer; + if (RETURN_ERROR (Status)) { + // + // Clear error bit + // + Index = Status & ~MAX_BIT; + if (Index > 0 && Index <= ERROR_STATUS_NUMBER) { + ArgumentString = mErrorString [Index - 1]; + } + } else { + Index = Status; + if (Index <= WARNING_STATUS_NUMBER) { + ArgumentString = mWarningString [Index]; + } + } + if (ArgumentString == ValueBuffer) { + BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status); + } + break; + + case '\r': + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + if (FormatCharacter == '\n') { + // + // Translate '\r\n' to '\r\n' + // + ArgumentString = "\r\n"; + } else { + // + // Translate '\r' to '\r' + // + ArgumentString = "\r"; + Format -= BytesPerFormatCharacter; + } + break; + + case '\n': + // + // Translate '\n' to '\r\n' and '\n\r' to '\r\n' + // + ArgumentString = "\r\n"; + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + if (FormatCharacter != '\r') { + Format -= BytesPerFormatCharacter; + } + break; + + case '%': + default: + // + // if the type is '%' or unknown, then print it to the screen + // + ArgumentString = (CHAR8 *)&FormatCharacter; + Flags |= ARGUMENT_UNICODE; + break; + } + break; + + case '\r': + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + if (FormatCharacter == '\n') { + // + // Translate '\r\n' to '\r\n' + // + ArgumentString = "\r\n"; + } else { + // + // Translate '\r' to '\r' + // + ArgumentString = "\r"; + Format -= BytesPerFormatCharacter; + } + break; + + case '\n': + // + // Translate '\n' to '\r\n' and '\n\r' to '\r\n' + // + ArgumentString = "\r\n"; + Format += BytesPerFormatCharacter; + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + if (FormatCharacter != '\r') { + Format -= BytesPerFormatCharacter; + } + break; + + default: + ArgumentString = (CHAR8 *)&FormatCharacter; + Flags |= ARGUMENT_UNICODE; + break; + } + + // + // Retrieve the ArgumentString attriubutes + // + if ((Flags & ARGUMENT_UNICODE) != 0) { + ArgumentMask = 0xffff; + BytesPerArgumentCharacter = 2; + } else { + ArgumentMask = 0xff; + BytesPerArgumentCharacter = 1; + } + if ((Flags & ARGUMENT_REVERSED) != 0) { + BytesPerArgumentCharacter = -BytesPerArgumentCharacter; + } else { + // + // Compute the number of characters in ArgumentString and store it in Count + // ArgumentString is either null-terminated, or it contains Precision characters + // + for (Count = 0; + (ArgumentString[Count * BytesPerArgumentCharacter] != '\0' || + (BytesPerArgumentCharacter > 1 && + ArgumentString[Count * BytesPerArgumentCharacter + 1]!= '\0')) && + (Count < Precision || ((Flags & PRECISION) == 0)); + Count++) { + ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask; + if (ArgumentCharacter == 0) { + break; + } + } + } + + if (Precision < Count) { + Precision = Count; + } + + // + // Pad before the string + // + if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) { + LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter); + } + } + + if (ZeroPad) { + if (Prefix != 0) { + LengthToReturn += (1 * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter); + } + } + LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter); + } + } else { + LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter); + } + if (Prefix != 0) { + LengthToReturn += (1 * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter); + } + } + } + + // + // Output the Prefix character if it is present + // + Index = 0; + if (Prefix != 0) { + Index++; + } + + // + // Copy the string into the output buffer performing the required type conversions + // + while (Index < Count && + (ArgumentString[0] != '\0' || + (BytesPerArgumentCharacter > 1 && ArgumentString[1] != '\0'))) { + ArgumentCharacter = ((*ArgumentString & 0xff) | (((UINT8)*(ArgumentString + 1)) << 8)) & ArgumentMask; + + LengthToReturn += (1 * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter); + } + ArgumentString += BytesPerArgumentCharacter; + Index++; + if (Comma) { + Digits++; + if (Digits == 3) { + Digits = 0; + Index++; + if (Index < Count) { + LengthToReturn += (1 * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter); + } + } + } + } + } + + // + // Pad after the string + // + if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) { + LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter); + if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) { + Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter); + } + } + + // + // Get the next character from the format string + // + Format += BytesPerFormatCharacter; + + // + // Get the next character from the format string + // + FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask; + } + + if ((Flags & COUNT_ONLY_NO_PRINT) != 0) { + return (LengthToReturn / BytesPerOutputCharacter); + } + + ASSERT (Buffer != NULL); + // + // Null terminate the Unicode or ASCII string + // + BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter); + + return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter); +} + +/** + Worker function that produces a Null-terminated string in an output buffer + based on a Null-terminated format string and variable argument list. + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this routine allows the nesting of Vararg routines. Thus + this is the main print working routine + + @param StartOfBuffer The character buffer to print the results of the parsing + of Format into. + @param BufferSize The maximum number of characters to put into buffer. + Zero means no limit. + @param Flags Initial flags value. + Can only have FORMAT_UNICODE and OUTPUT_UNICODE set + @param FormatString A Null-terminated format string. + @param ... The variable argument list. + + @return The number of characters printed. + +**/ +UINTN +EFIAPI +BasePrintLibSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + UINTN NumberOfPrinted; + + VA_START (Marker, FormatString); + NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL); + VA_END (Marker); + return NumberOfPrinted; +} diff --git a/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h new file mode 100644 index 000000000..c20a582a4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h @@ -0,0 +1,271 @@ +/** @file + Base Print Library instance Internal Functions definition. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PRINT_LIB_INTERNAL_H__ +#define __PRINT_LIB_INTERNAL_H__ + +#include +#include +#include +#include +#include + + +// +// Print primitives +// +#define PREFIX_SIGN BIT1 +#define PREFIX_BLANK BIT2 +#define LONG_TYPE BIT4 +#define OUTPUT_UNICODE BIT6 +#define FORMAT_UNICODE BIT8 +#define PAD_TO_WIDTH BIT9 +#define ARGUMENT_UNICODE BIT10 +#define PRECISION BIT11 +#define ARGUMENT_REVERSED BIT12 +#define COUNT_ONLY_NO_PRINT BIT13 +#define UNSIGNED_TYPE BIT14 + +// +// Record date and time information +// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} TIME; + +/** + Worker function that produces a Null-terminated string in an output buffer + based on a Null-terminated format string and a VA_LIST argument list. + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this routine allows the nesting of Vararg routines. Thus + this is the main print working routine. + + If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all. + + @param[out] Buffer The character buffer to print the results of the + parsing of Format into. + @param[in] BufferSize The maximum number of characters to put into + buffer. + @param[in] Flags Initial flags value. + Can only have FORMAT_UNICODE, OUTPUT_UNICODE, + and COUNT_ONLY_NO_PRINT set. + @param[in] Format A Null-terminated format string. + @param[in] VaListMarker VA_LIST style variable argument list consumed by + processing Format. + @param[in] BaseListMarker BASE_LIST style variable argument list consumed + by processing Format. + + @return The number of characters printed not including the Null-terminator. + If COUNT_ONLY_NO_PRINT was set returns the same, but without any + modification to Buffer. + +**/ +UINTN +BasePrintLibSPrintMarker ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, OPTIONAL + IN BASE_LIST BaseListMarker OPTIONAL + ); + +/** + Worker function that produces a Null-terminated string in an output buffer + based on a Null-terminated format string and variable argument list. + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this routine allows the nesting of Vararg routines. Thus + this is the main print working routine + + @param StartOfBuffer The character buffer to print the results of the parsing + of Format into. + @param BufferSize The maximum number of characters to put into buffer. + Zero means no limit. + @param Flags Initial flags value. + Can only have FORMAT_UNICODE and OUTPUT_UNICODE set + @param FormatString Null-terminated format string. + @param ... The variable argument list. + + @return The number of characters printed. + +**/ +UINTN +EFIAPI +BasePrintLibSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *FormatString, + ... + ); + +/** + Internal function that places the character into the Buffer. + + Internal function that places ASCII or Unicode character into the Buffer. + + @param Buffer Buffer to place the Unicode or ASCII string. + @param EndBuffer The end of the input Buffer. No characters will be + placed after that. + @param Length The count of character to be placed into Buffer. + (Negative value indicates no buffer fill.) + @param Character The character to be placed into Buffer. + @param Increment The character increment in Buffer. + + @return Buffer Buffer filled with the input Character. + +**/ +CHAR8 * +BasePrintLibFillBuffer ( + OUT CHAR8 *Buffer, + IN CHAR8 *EndBuffer, + IN INTN Length, + IN UINTN Character, + IN INTN Increment + ); + +/** + Internal function that convert a number to a string in Buffer. + + Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer. + + @param Buffer Location to place the ASCII string of Value. + @param Value The value to convert to a Decimal or Hexadecimal string in Buffer. + @param Radix Radix of the value + + @return A pointer to the end of buffer filled with ASCII string. + +**/ +CHAR8 * +BasePrintLibValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Radix + ); + +/** + Internal function that converts a decimal value to a Null-terminated string. + + Converts the decimal number specified by Value to a Null-terminated + string specified by Buffer containing at most Width characters. + If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed. + The total number of characters placed in Buffer is returned. + If the conversion contains more than Width characters, then only the first + Width characters are returned, and the total number of characters + required to perform the conversion is returned. + Additional conversion parameters are specified in Flags. + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas + are inserted every 3rd digit starting from the right. + If Value is < 0, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional '-' + sign character, '0' characters, digit characters for Value, and the Null-terminator + add up to Width characters. + + If Buffer is NULL, then ASSERT(). + If unsupported bits are set in Flags, then ASSERT(). + If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT() + + @param Buffer The pointer to the output buffer for the produced Null-terminated + string. + @param Flags The bitmask of flags that specify left justification, zero pad, + and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of characters to place in Buffer, not including + the Null-terminator. + @param Increment Character increment in Buffer. + + @return Total number of characters required to perform the conversion. + +**/ +UINTN +BasePrintLibConvertValueToString ( + IN OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width, + IN UINTN Increment + ); + +/** + Internal function that converts a decimal value to a Null-terminated string. + + Converts the decimal number specified by Value to a Null-terminated string + specified by Buffer containing at most Width characters. If Width is 0 then a + width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more + than Width characters, then only the first Width characters are placed in + Buffer. Additional conversion parameters are specified in Flags. + The Flags bit LEFT_JUSTIFY is always ignored. + All conversions are left justified in Buffer. + If Width is 0, PREFIX_ZERO is ignored in Flags. + If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and + commas are inserted every 3rd digit starting from the right. + If Value is < 0, then the fist character in Buffer is a '-'. + If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, + then Buffer is padded with '0' characters so the combination of the optional + '-' sign character, '0' characters, digit characters for Value, and the + Null-terminator add up to Width characters. + + If an error would be returned, the function will ASSERT(). + + @param Buffer The pointer to the output buffer for the produced + Null-terminated string. + @param BufferSize The size of Buffer in bytes, including the + Null-terminator. + @param Flags The bitmask of flags that specify left justification, + zero pad, and commas. + @param Value The 64-bit signed value to convert to a string. + @param Width The maximum number of characters to place in Buffer, + not including the Null-terminator. + @param Increment The character increment in Buffer. + + @retval RETURN_SUCCESS The decimal value is converted. + @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted + value. + @retval RETURN_INVALID_PARAMETER If Buffer is NULL. + If Increment is 1 and + PcdMaximumAsciiStringLength is not zero, + BufferSize is greater than + PcdMaximumAsciiStringLength. + If Increment is not 1 and + PcdMaximumUnicodeStringLength is not zero, + BufferSize is greater than + (PcdMaximumUnicodeStringLength * + sizeof (CHAR16) + 1). + If unsupported bits are set in Flags. + If both COMMA_TYPE and RADIX_HEX are set in + Flags. + If Width >= MAXIMUM_VALUE_CHARACTERS. + +**/ +RETURN_STATUS +BasePrintLibConvertValueToStringS ( + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width, + IN UINTN Increment + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c new file mode 100644 index 000000000..48ef2d6b3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c @@ -0,0 +1,386 @@ +/** @file + Null Base Report Status Code Library instance with empty functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + 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 + ) +{ + ASSERT (PostCode != NULL); + + 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 The pointer to the status code data buffer. + @param Filename The pointer to the source file name that generated the ASSERT(). + @param Description The pointer to the description of the ASSERT(). + @param LineNumber The pointer to the 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 + ) +{ + 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 The pointer to the status code data buffer. + @param ErrorLevel The pointer to the error level mask for a debug message. + @param Marker The pointer to the variable argument list associated with Format. + @param Format The 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 + ) +{ + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + return FALSE; +} + + +/** + 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 recursion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type The status code type. + @param Value The 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 The report status code is not supported. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return EFI_SUCCESS; +} + + +/** + 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 The 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 The 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 EFI_SUCCESS; +} + + +/** + 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 The 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 The 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 EFI_SUCCESS; +} + + +/** + 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 The status code type. + @param Value The status code value. + @param Instance Status code instance number. + @param CallerId The 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 The 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 The 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 The 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 + ) +{ + return EFI_SUCCESS; +} + + +/** + 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 FALSE; +} + + +/** + 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 FALSE; +} + + +/** + 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 FALSE; +} + diff --git a/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf new file mode 100644 index 000000000..d43c4dd51 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf @@ -0,0 +1,34 @@ +## @file +# Report Status Code Library with empty functions. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseReportStatusCodeLibNull + MODULE_UNI_FILE = BaseReportStatusCodeLibNull.uni + FILE_GUID = 1DE0B8C2-FFB6-4bdf-97F5-0FFB33979038 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ReportStatusCodeLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseReportStatusCodeLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni new file mode 100644 index 000000000..602157581 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Report Status Code Library with empty functions. +// +// Report Status Code Library with empty functions. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Report Status Code Library with empty functions" + +#string STR_MODULE_DESCRIPTION #language en-US "Report Status Code Library with empty functions." + diff --git a/roms/edk2/MdePkg/Library/BaseRngLib/BaseRng.c b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRng.c new file mode 100644 index 000000000..7ad7aec9d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRng.c @@ -0,0 +1,183 @@ +/** @file + Random number generator services that uses RdRand instruction access + to provide high-quality random numbers. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +// +// Bit mask used to determine if RdRand instruction is supported. +// +#define RDRAND_MASK BIT30 + +// +// Limited retry number when valid random data is returned. +// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32 +// Architectures Software Developer's Mannual". +// +#define RDRAND_RETRY_LIMIT 10 + +/** + The constructor function checks whether or not RDRAND instruction is supported + by the host hardware. + + The constructor function checks whether or not RDRAND instruction is supported. + It will ASSERT() if RDRAND instruction is not supported. + It will always return RETURN_SUCCESS. + + @retval RETURN_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +BaseRngLibConstructor ( + VOID + ) +{ + UINT32 RegEcx; + + // + // Determine RDRAND support by examining bit 30 of the ECX register returned by + // CPUID. A value of 1 indicates that processor support RDRAND instruction. + // + AsmCpuid (1, 0, 0, &RegEcx, 0); + ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK); + + return RETURN_SUCCESS; +} + +/** + Generates a 16-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 16-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber16 ( + OUT UINT16 *Rand + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + // + // A loop to fetch a 16 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand16 (Rand)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Generates a 32-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 32-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber32 ( + OUT UINT32 *Rand + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + // + // A loop to fetch a 32 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand32 (Rand)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Generates a 64-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber64 ( + OUT UINT64 *Rand + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + // + // A loop to fetch a 64 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand64 (Rand)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Generates a 128-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 128-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber128 ( + OUT UINT64 *Rand + ) +{ + ASSERT (Rand != NULL); + + // + // Read first 64 bits + // + if (!GetRandomNumber64 (Rand)) { + return FALSE; + } + + // + // Read second 64 bits + // + return GetRandomNumber64 (++Rand); +} diff --git a/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf new file mode 100644 index 000000000..31740751c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf @@ -0,0 +1,36 @@ +## @file +# Instance of RNG (Random Number Generator) Library. +# +# BaseRng Library that uses CPU RdRand instruction access to provide +# high-quality random numbers. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseRngLib + MODULE_UNI_FILE = BaseRngLib.uni + FILE_GUID = 626440D8-1971-41D9-9AB2-FB25F4AE79BC + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RngLib + CONSTRUCTOR = BaseRngLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32, Sources.X64] + BaseRng.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib diff --git a/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni new file mode 100644 index 000000000..f3ed954c5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of RNG (Random Number Generator) Library. +// +// BaseRng Library that uses CPU RdRand instruction access to provide +// high-quality random numbers. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library" + +#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RdRand instruction access to provide high-quality random numbers" + diff --git a/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.c b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.c new file mode 100644 index 000000000..cad30599e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.c @@ -0,0 +1,94 @@ +/** @file + Null version of Random number generator services. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Generates a 16-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 16-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber16 ( + OUT UINT16 *Rand + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates a 32-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 32-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber32 ( + OUT UINT32 *Rand + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates a 64-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber64 ( + OUT UINT64 *Rand + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates a 128-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 128-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber128 ( + OUT UINT64 *Rand + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf new file mode 100644 index 000000000..f21e20a9c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf @@ -0,0 +1,30 @@ +## @file +# Null instance of RNG (Random Number Generator) Library. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010029 + BASE_NAME = BaseRngLibNull + MODULE_UNI_FILE = BaseRngLibNull.uni + FILE_GUID = CD8991F8-2061-4084-8C9E-9C6F352DC58D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RngLib + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 EBC +# + +[Sources] + BaseRngLibNull.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib diff --git a/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.uni b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.uni new file mode 100644 index 000000000..f32be6a61 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseRngLibNull/BaseRngLibNull.uni @@ -0,0 +1,14 @@ +// /** @file +// Null Instance of RNG (Random Number Generator) Library. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Null Instance of RNG Library" + +#string STR_MODULE_DESCRIPTION #language en-US "This library instance should be used with modules that inherit an (indirect) dependency on the RngLib class, but never actually call RngLib APIs for consuming randomness." + diff --git a/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf new file mode 100644 index 000000000..4c2d5cb67 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf @@ -0,0 +1,37 @@ +## @file +# BootScriptLib instance that always produces NOP operation. +# +# This library is primarily used by platform that does not support ACPI S3 +# resume. All the library interfaces simply return EFI_SUCCESS without +# performing any operation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3BootScriptLibNull + MODULE_UNI_FILE = BaseS3BootScriptLibNull.uni + FILE_GUID = 9A6DC1AC-94C0-43b1-8714-4C70FD58A815 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3BootScriptLib + + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BootScriptLib.c + + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni new file mode 100644 index 000000000..58991a31c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni @@ -0,0 +1,18 @@ +// /** @file +// BootScriptLib instance that always produces NOP operation. +// +// This library is primarily used by platform that does not support ACPI S3 +// resume. All the library interfaces simply return EFI_SUCCESS without +// performing any operation. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "BootScriptLib instance that always produces NOP operation" + +#string STR_MODULE_DESCRIPTION #language en-US "This library is primarily used by a platform that does not support ACPI S3 resume. All the library interfaces simply return EFI_SUCCESS without performing any operation." + diff --git a/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c new file mode 100644 index 000000000..f150e8b2e --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c @@ -0,0 +1,561 @@ +/** @file + Null function implementation for EFI S3 boot script. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include + +/** + Save I/O write to boot script + + @param Width the width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The base address of the I/O operations. + @param Count The number of I/O operations to perform. + @param Buffer The source buffer from which to write data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RETURN_SUCCESS; +} + +/** + Adds a record for an I/O modify operation into a S3 boot script table + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The base address of the I/O operations. + @param Data A pointer to the data to be OR-ed. + @param DataMask A pointer to the data mask to be AND-ed with the data read from the register + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ) +{ + return RETURN_SUCCESS; +} + +/** + Adds a record for a memory write operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The base address of the memory operations + @param Count The number of memory operations to perform. + @param Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveMemWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for a memory modify operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The base address of the memory operations. Address needs alignment if required + @param Data A pointer to the data to be OR-ed. + @param DataMask A pointer to the data mask to be AND-ed with the data read from the register. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveMemReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for a PCI configuration space write operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The address within the PCI configuration space. + @param Count The number of PCI operations to perform. + @param Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfgWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RETURN_SUCCESS; +} + +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Address The address within the PCI configuration space. + @param Data A pointer to the data to be OR-ed.The size depends on Width. + @param DataMask A pointer to the data mask to be AND-ed. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN__SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfgReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Segment The PCI segment number for Address. + @param Address The address within the PCI configuration space. + @param Count The number of PCI operations to perform. + @param Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfg2Write ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT16 Segment, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH. + @param Segment The PCI segment number for Address. + @param Address The address within the PCI configuration space. + @param Data A pointer to the data to be OR-ed. The size depends on Width. + @param DataMask A pointer to the data mask to be AND-ed. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfg2ReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT16 Segment, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for an SMBus command execution into a specified boot script table. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC. + @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus + transactions. + @param Length A pointer to signify the number of bytes that this operation will do. + @param Buffer Contains the value of data to execute to the SMBUS slave device. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveSmbusExecute ( + IN UINTN SmBusAddress, + IN EFI_SMBUS_OPERATION Operation, + IN UINTN *Length, + IN VOID *Buffer + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for an execution stall on the processor into a specified boot script table. + + @param Duration Duration in microseconds of the stall + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveStall ( + IN UINTN Duration + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for dispatching specified arbitrary code into a specified boot script table. + + @param EntryPoint Entry point of the code to be dispatched. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveDispatch ( + IN VOID *EntryPoint + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for dispatching specified arbitrary code into a specified boot script table. + + @param EntryPoint Entry point of the code to be dispatched. + @param Context Argument to be passed into the EntryPoint of the code to be dispatched. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveDispatch2 ( + IN VOID *EntryPoint, + IN VOID *Context + ) +{ + return RETURN_SUCCESS; +} + +/** + Adds a record for memory reads of the memory location and continues when the exit criteria is + satisfied or after a defined duration. + + Please aware, below interface is different with PI specification, Vol 5: + EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE. + "Duration" below is microseconds, while "Delay" in PI specification means + the number of 100ns units to poll. + + @param Width The width of the memory operations. + @param Address The base address of the memory operations. + @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register. + @param BitValue A pointer to the data value after to be Masked. + @param Duration Duration in microseconds of the stall. + @param LoopTimes The times of the register polling. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveMemPoll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *BitMask, + IN VOID *BitValue, + IN UINTN Duration, + IN UINT64 LoopTimes + ) +{ + return RETURN_SUCCESS; +} + +/** + Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only + used for debugging script issues. + + @param InformationLength Length of the data in bytes + @param Information Information to be logged in the boot scrpit + + @retval RETURN_UNSUPPORTED If entering runtime, this method will not support. + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveInformation ( + IN UINT32 InformationLength, + IN VOID *Information + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a + defined duration. + + @param Width The width of the I/O operations. + @param Address The base address of the I/O operations. + @param Data The comparison value used for the polling exit criteria. + @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero + in Data are ignored when polling the memory address. + @param Delay The number of 100ns units to poll. Note that timer available may be of poorer + granularity so the delay may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoPoll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask, + IN UINT64 Delay + ) +{ + return RETURN_SUCCESS; +} + +/** + Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or + after a defined duration. + + @param Width The width of the I/O operations. + @param Address The address within the PCI configuration space. + @param Data The comparison value used for the polling exit criteria. + @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero + in Data are ignored when polling the memory address + @param Delay The number of 100ns units to poll. Note that timer available may be of poorer + granularity so the delay may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciPoll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask, + IN UINT64 Delay + ) +{ + return RETURN_SUCCESS; +} +/** + Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or + after a defined duration. + + @param Width The width of the I/O operations. + @param Segment The PCI segment number for Address. + @param Address The address within the PCI configuration space. + @param Data The comparison value used for the polling exit criteria. + @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero + in Data are ignored when polling the memory address + @param Delay The number of 100ns units to poll. Note that timer available may be of poorer + granularity so the delay may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation. + @retval RETURN_SUCCESS Opcode is added. + @note A known Limitations in the implementation: When interpreting the opcode EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE + EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as + Zero, or else, assert. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePci2Poll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT16 Segment, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask, + IN UINT64 Delay + ) +{ + return RETURN_SUCCESS; +} +/** + Save ASCII string information specified by Buffer to + boot script with opcode EFI_BOOT_SCRIPT_INFORMATION_OPCODE + + @param String the ascii string to store into the S3 boot script table + + @retval RETURN_NOT_FOUND BootScriptSave Protocol not exist. + @retval RETURN_SUCCESS BootScriptSave Protocol exist, always returns RETURN_SUCCESS + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveInformationAsciiString ( + IN CONST CHAR8 *String + ) +{ + return RETURN_SUCCESS; +} +/** + This is an function to close the S3 boot script table. The function could only be called in + BOOT time phase. To comply with the Framework spec definition on + EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things: + 1. Closes the specified boot script table + 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table. + Once this function is called, the table maintained by the library will be destroyed + after it is copied into the allocated pool. + 3. Any attempts to add a script record after calling this function will cause a new table + to be created by the library. + 4. The base address of the allocated pool will be returned in Address. Note that after + using the boot script table, the CALLER is responsible for freeing the pool that is allocated + by this function. + + In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. By then it is not + necessary to provide this API in BootScriptLib. To provides this API for now is only to meet + the requirement from Framework Spec. + + If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out + how to get the script to run on an S3 resume because the boot script maintained by the lib will be + destroyed. + + @return the base address of the new copy of the boot script table. + +**/ +UINT8* +EFIAPI +S3BootScriptCloseTable ( + VOID + ) +{ + return 0; +} +/** + Executes the S3 boot script table. + + @param RETURN_SUCCESS The boot script table was executed successfully. + @param RETURN_UNSUPPORTED Invalid script table or opcode. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptExecute ( + VOID + ) +{ + return RETURN_SUCCESS; +} +/** + Move the last boot script entry to the position + + @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position + in the boot script table specified by Position. If Position is NULL or points to + NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end + of the table (if FALSE). + @param Position On entry, specifies the position in the boot script table where the opcode will be + inserted, either before or after, depending on BeforeOrAfter. On exit, specifies + the position of the inserted opcode in the boot script table. + + @retval RETURN_OUT_OF_RESOURCES The table is not available. + @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table. + @retval RETURN_SUCCESS Opcode is inserted. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptMoveLastOpcode ( + IN BOOLEAN BeforeOrAfter, + IN OUT VOID **Position OPTIONAL +) +{ + return RETURN_SUCCESS; +} +/** + Find a label within the boot script table and, if not present, optionally create it. + + @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) + or after (FALSE) the position in the boot script table + specified by Position. + @param CreateIfNotFound Specifies whether the label will be created if the label + does not exists (TRUE) or not (FALSE). + @param Position On entry, specifies the position in the boot script table + where the opcode will be inserted, either before or after, + depending on BeforeOrAfter. On exit, specifies the position + of the inserted opcode in the boot script table. + @param Label Points to the label which will be inserted in the boot script table. + + @retval EFI_SUCCESS The operation succeeded. A record was added into the + specified script table. + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + If the opcode is unknow or not supported because of the PCD + Feature Flags. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptLabel ( + IN BOOLEAN BeforeOrAfter, + IN BOOLEAN CreateIfNotFound, + IN OUT VOID **Position OPTIONAL, + IN CONST CHAR8 *Label + ) +{ + return RETURN_SUCCESS; +} +/** + Compare two positions in the boot script table and return their relative position. + @param Position1 The positions in the boot script table to compare + @param Position2 The positions in the boot script table to compare + @param RelativePosition On return, points to the result of the comparison + + @retval EFI_SUCCESS The operation succeeded. A record was added into the + specified script table. + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + If the opcode is unknow or not supported because of the PCD + Feature Flags. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptCompare ( + IN UINT8 *Position1, + IN UINT8 *Position2, + OUT UINTN *RelativePosition + ) +{ + return RETURN_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf b/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf new file mode 100644 index 000000000..0f0db448b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf @@ -0,0 +1,40 @@ +## @file +# Instance of S3 I/O Library based on I/O and S3 BootScript Library. +# +# S3 I/O and MMIO Library Services that do I/O and also +# enable the I/O operatation to be replayed during an S3 resume. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3IoLib + MODULE_UNI_FILE = BaseS3IoLib.uni + FILE_GUID = B13F938E-47DF-4516-A397-8927A4E42B61 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3IoLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + S3IoLib.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + IoLib + S3BootScriptLib + diff --git a/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni b/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni new file mode 100644 index 000000000..7229f0002 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of S3 I/O Library based on I/O and S3 BootScript Library. +// +// S3 I/O and MMIO Library Services that do I/O and also +// enable the I/O operatation to be replayed during an S3 resume. +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of S3 I/O Library based on I/O and S3 BootScript Library" + +#string STR_MODULE_DESCRIPTION #language en-US "S3 I/O and MMIO Library Services that do I/O and also enable the I/O operation to be replayed during an S3 resume." + diff --git a/roms/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c b/roms/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c new file mode 100644 index 000000000..c68a43329 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c @@ -0,0 +1,3305 @@ +/** @file + I/O and MMIO Library Services that do I/O and also enable the I/O operatation + to be replayed during an S3 resume. + + Copyright (c) 2006 -2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + + +/** + Saves an I/O port value to the boot script. + + This internal worker function saves an I/O port value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Width The width of I/O port. + @param Port The I/O port to write. + @param Buffer The buffer containing value. + +**/ +VOID +InternalSaveIoWriteValueToBootScript ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINTN Port, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSaveIoWrite ( + Width, + Port, + 1, + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); +} + +/** + Saves an 8-bit I/O port value to the boot script. + + This internal worker function saves an 8-bit I/O port value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT8 +InternalSaveIoWrite8ValueToBootScript ( + IN UINTN Port, + IN UINT8 Value + ) +{ + InternalSaveIoWriteValueToBootScript (S3BootScriptWidthUint8, Port, &Value); + + return Value; +} + +/** + Reads an 8-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3IoRead8 ( + IN UINTN Port + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoRead8 (Port)); +} + +/** + Writes an 8-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +S3IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoWrite8 (Port, Value)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise OR, and writes the + result back to the 8-bit I/O port and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoOr8 (Port, OrData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoAnd8 (Port, AndData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoAndThenOr8 (Port, AndData, OrData)); +} + +/** + Reads a bit field of an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoBitFieldRead8 (Port, StartBit, EndBit)); +} + +/** + Writes a bit field to an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoBitFieldWrite8 (Port, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoBitFieldOr8 (Port, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoBitFieldAnd8 (Port, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +S3IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSaveIoWrite8ValueToBootScript (Port, IoBitFieldAndThenOr8 (Port, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 16-bit I/O port value to the boot script. + + This internal worker function saves a 16-bit I/O port value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT16 +InternalSaveIoWrite16ValueToBootScript ( + IN UINTN Port, + IN UINT16 Value + ) +{ + InternalSaveIoWriteValueToBootScript (S3BootScriptWidthUint16, Port, &Value); + + return Value; +} + +/** + Reads a 16-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3IoRead16 ( + IN UINTN Port + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoRead16 (Port)); +} + +/** + Writes a 16-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +S3IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoWrite16 (Port, Value)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise OR, and writes the + result back to the 16-bit I/O port and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoOr16 (Port, OrData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoAnd16 (Port, AndData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoAndThenOr16 (Port, AndData, OrData)); +} + +/** + Reads a bit field of an I/O register saves the value in the S3 script to be + replayed on S3 resume. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoBitFieldRead16 (Port, StartBit, EndBit)); +} + +/** + Writes a bit field to an I/O register and saves the value in the S3 script + to be replayed on S3 resume. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoBitFieldWrite16 (Port, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoBitFieldOr16 (Port, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoBitFieldAnd16 (Port, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port and saves the value in the S3 script to be replayed on S3 + resume. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +S3IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSaveIoWrite16ValueToBootScript (Port, IoBitFieldAndThenOr16 (Port, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 32-bit I/O port value to the boot script. + + This internal worker function saves a 32-bit I/O port value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT32 +InternalSaveIoWrite32ValueToBootScript ( + IN UINTN Port, + IN UINT32 Value + ) +{ + InternalSaveIoWriteValueToBootScript (S3BootScriptWidthUint32, Port, &Value); + + return Value; +} + +/** + Reads a 32-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3IoRead32 ( + IN UINTN Port + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoRead32 (Port)); +} + +/** + Writes a 32-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +S3IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoWrite32 (Port, Value)); +} + +/** + Reads a 32-bit I/O port, performs a bitwise OR, and writes the + result back to the 32-bit I/O port and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoOr32 (Port, OrData)); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoAnd32 (Port, AndData)); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoAndThenOr32 (Port, AndData, OrData)); +} + +/** + Reads a bit field of an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoBitFieldRead32 (Port, StartBit, EndBit)); +} + +/** + Writes a bit field to an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoBitFieldWrite32 (Port, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoBitFieldOr32 (Port, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoBitFieldAnd32 (Port, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port and saves the value in the S3 script to be replayed on S3 + resume. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +S3IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSaveIoWrite32ValueToBootScript (Port, IoBitFieldAndThenOr32 (Port, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 64-bit I/O port value to the boot script. + + This internal worker function saves a 64-bit I/O port value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT64 +InternalSaveIoWrite64ValueToBootScript ( + IN UINTN Port, + IN UINT64 Value + ) +{ + InternalSaveIoWriteValueToBootScript (S3BootScriptWidthUint64, Port, &Value); + + return Value; +} + +/** + Reads a 64-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3IoRead64 ( + IN UINTN Port + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoRead64 (Port)); +} + +/** + Writes a 64-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +S3IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoWrite64 (Port, Value)); +} + +/** + Reads a 64-bit I/O port, performs a bitwise OR, and writes the + result back to the 64-bit I/O port and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoOr64 (Port, OrData)); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoAnd64 (Port, AndData)); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoAndThenOr64 (Port, AndData, OrData)); +} + +/** + Reads a bit field of an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoBitFieldRead64 (Port, StartBit, EndBit)); +} + +/** + Writes a bit field to an I/O register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoBitFieldWrite64 (Port, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoBitFieldOr64 (Port, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoBitFieldAnd64 (Port, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit port and saves the value in the S3 script to be replayed on S3 + resume. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return InternalSaveIoWrite64ValueToBootScript (Port, IoBitFieldAndThenOr64 (Port, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves an MMIO register value to the boot script. + + This internal worker function saves an MMIO register value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Width The width of MMIO register. + @param Address The MMIO register to write. + @param Buffer The buffer containing value. + +**/ +VOID +InternalSaveMmioWriteValueToBootScript ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINTN Address, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSaveMemWrite ( + Width, + Address, + 1, + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); +} + +/** + Saves an 8-bit MMIO register value to the boot script. + + This internal worker function saves an 8-bit MMIO register value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT8 +InternalSaveMmioWrite8ValueToBootScript ( + IN UINTN Address, + IN UINT8 Value + ) +{ + InternalSaveMmioWriteValueToBootScript (S3BootScriptWidthUint8, Address, &Value); + + return Value; +} + +/** + Reads an 8-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3MmioRead8 ( + IN UINTN Address + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioRead8 (Address)); +} + +/** + Writes an 8-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return The value written the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioWrite8 (Address, Value)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, and writes the + result back to the 8-bit MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioOr8 (Address, OrData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioAnd8 (Address, AndData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioAndThenOr8 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a MMIO register and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioBitFieldRead8 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to an MMIO register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioBitFieldWrite8 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioBitFieldOr8 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioBitFieldAnd8 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 8-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +S3MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSaveMmioWrite8ValueToBootScript (Address, MmioBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 16-bit MMIO register value to the boot script. + + This internal worker function saves a 16-bit MMIO register value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT16 +InternalSaveMmioWrite16ValueToBootScript ( + IN UINTN Address, + IN UINT16 Value + ) +{ + InternalSaveMmioWriteValueToBootScript (S3BootScriptWidthUint16, Address, &Value); + + return Value; +} + +/** + Reads a 16-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3MmioRead16 ( + IN UINTN Address + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioRead16 (Address)); +} + +/** + Writes a 16-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized and saves the value in the S3 script to be + replayed on S3 resume. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return The value written the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioWrite16 (Address, Value)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, and writes the + result back to the 16-bit MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioOr16 (Address, OrData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioAnd16 (Address, AndData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioAndThenOr16 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a MMIO register and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioBitFieldRead16 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a MMIO register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioBitFieldWrite16 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioBitFieldOr16 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioBitFieldAnd16 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 16-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +S3MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSaveMmioWrite16ValueToBootScript (Address, MmioBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 32-bit MMIO register value to the boot script. + + This internal worker function saves a 32-bit MMIO register value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT32 +InternalSaveMmioWrite32ValueToBootScript ( + IN UINTN Address, + IN UINT32 Value + ) +{ + InternalSaveMmioWriteValueToBootScript (S3BootScriptWidthUint32, Address, &Value); + + return Value; +} + +/** + Reads a 32-bit MMIO register saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3MmioRead32 ( + IN UINTN Address + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioRead32 (Address)); +} + +/** + Writes a 32-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return The value written the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioWrite32 (Address, Value)); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, and writes the + result back to the 32-bit MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioOr32 (Address, OrData)); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioAnd32 (Address, AndData)); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioAndThenOr32 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioBitFieldRead32 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioBitFieldWrite32 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioBitFieldOr32 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioBitFieldAnd32 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 32-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +S3MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSaveMmioWrite32ValueToBootScript (Address, MmioBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 64-bit MMIO register value to the boot script. + + This internal worker function saves a 64-bit MMIO register value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT64 +InternalSaveMmioWrite64ValueToBootScript ( + IN UINTN Address, + IN UINT64 Value + ) +{ + InternalSaveMmioWriteValueToBootScript (S3BootScriptWidthUint64, Address, &Value); + + return Value; +} + +/** + Reads a 64-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3MmioRead64 ( + IN UINTN Address + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioRead64 (Address)); +} + +/** + Writes a 64-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return The value written the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioWrite64 (Address, Value)); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, and writes the + result back to the 64-bit MMIO register and saves the value in the S3 script + to be replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioOr64 (Address, OrData)); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register and saves the value in the S3 script to be + replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioAnd64 (Address, AndData)); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioAndThenOr64 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a MMIO register saves the value in the S3 script to + be replayed on S3 resume. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioBitFieldRead64 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a MMIO register and saves the value in the S3 script to + be replayed on S3 resume. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioBitFieldWrite64 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioBitFieldOr64 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioBitFieldAnd64 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 64-bit MMIO register and saves the value in the S3 script to be replayed + on S3 resume. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +S3MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return InternalSaveMmioWrite64ValueToBootScript (Address, MmioBitFieldAndThenOr64 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Copy data from MMIO region to system memory by using 8-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 8-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + + @param StartAddress Starting address for the MMIO region to be copied from. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +S3MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioReadBuffer8 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint8, + StartAddress, + Length / sizeof (UINT8), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 16-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 16-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied from. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT16 * +EFIAPI +S3MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioReadBuffer16 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint16, + StartAddress, + Length / sizeof (UINT16), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 32-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 32-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied from. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT32 * +EFIAPI +S3MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioReadBuffer32 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint32, + StartAddress, + Length / sizeof (UINT32), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 64-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 64-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied from. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT64 * +EFIAPI +S3MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioReadBuffer64 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint64, + StartAddress, + Length / sizeof (UINT64), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 8-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 8-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + + @param StartAddress Starting address for the MMIO region to be copied to. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT8 * +EFIAPI +S3MmioWriteBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioWriteBuffer8 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint8, + StartAddress, + Length / sizeof (UINT8), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + +/** + Copy data from system memory to MMIO region by using 16-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 16-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied to. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT16 * +EFIAPI +S3MmioWriteBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioWriteBuffer16 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint16, + StartAddress, + Length / sizeof (UINT16), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 32-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 32-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied to. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT32 * +EFIAPI +S3MmioWriteBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioWriteBuffer32 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint32, + StartAddress, + Length / sizeof (UINT32), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + +/** + Copy data from system memory to MMIO region by using 64-bit access + and saves the value in the S3 script to be replayed on S3 resume. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 64-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress Starting address for the MMIO region to be copied to. + @param Length Size in bytes of the copy. + @param Buffer Pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT64 * +EFIAPI +S3MmioWriteBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + RETURN_STATUS Status; + + ReturnBuffer = MmioWriteBuffer64 (StartAddress, Length, Buffer); + + Status = S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint64, + StartAddress, + Length / sizeof (UINT64), + ReturnBuffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return ReturnBuffer; +} + diff --git a/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf b/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf new file mode 100644 index 000000000..d32d12798 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf @@ -0,0 +1,41 @@ +## @file +# Instance of S3 PCI Library based on PCI and S3 BootScript Library. +# +# S3 PCI Services that perform PCI Configuration cycles and +# also enable the PCI operation to be replayed during an S3 resume. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3PciLib + MODULE_UNI_FILE = BaseS3PciLib.uni + FILE_GUID = F66B6BD2-513F-441d-B367-2D5BD4998A50 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3PciLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + S3PciLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + PciLib + S3BootScriptLib + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni b/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni new file mode 100644 index 000000000..137d5f39b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of S3 PCI Library based on PCI and S3 BootScript Library. +// +// S3 PCI Services that perform PCI Configuration cycles and +// also enable the PCI operation to be replayed during an S3 resume. +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of S3 PCI Library based on PCI and S3 BootScript Library" + +#string STR_MODULE_DESCRIPTION #language en-US "S3 PCI Services that perform PCI Configuration cycles and also enable the PCI operation to be replayed during an S3 resume." + diff --git a/roms/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c b/roms/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c new file mode 100644 index 000000000..cae12a1f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c @@ -0,0 +1,1262 @@ +/** @file + PCI configuration Library Services that do PCI configuration and also enable + the PCI operations to be replayed during an S3 resume. This library class + maps directly on top of the PciLib class. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +#define PCILIB_TO_COMMON_ADDRESS(Address) \ + ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))) + +/** + Saves a PCI configuration value to the boot script. + + This internal worker function saves a PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Width The width of PCI configuration. + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Buffer The buffer containing value. + +**/ +VOID +InternalSavePciWriteValueToBootScript ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINTN Address, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfgWrite ( + Width, + PCILIB_TO_COMMON_ADDRESS(Address), + 1, + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); +} + +/** + Saves an 8-bit PCI configuration value to the boot script. + + This internal worker function saves an 8-bit PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT8 +InternalSavePciWrite8ValueToBootScript ( + IN UINTN Address, + IN UINT8 Value + ) +{ + InternalSavePciWriteValueToBootScript (S3BootScriptWidthUint8, Address, &Value); + + return Value; +} + +/** + Reads an 8-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciRead8 ( + IN UINTN Address + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciRead8 (Address)); +} + +/** + Writes an 8-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciWrite8 (Address, Value)); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciOr8 (Address, OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciAnd8 (Address, AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciAndThenOr8 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciBitFieldRead8 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciBitFieldWrite8 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port and saves the value + in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciBitFieldOr8 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciBitFieldAnd8 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in an 8-bit Address, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSavePciWrite8ValueToBootScript (Address, PciBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 16-bit PCI configuration value to the boot script. + + This internal worker function saves a 16-bit PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return Value. + +**/ +UINT16 +InternalSavePciWrite16ValueToBootScript ( + IN UINTN Address, + IN UINT16 Value + ) +{ + InternalSavePciWriteValueToBootScript (S3BootScriptWidthUint16, Address, &Value); + + return Value; +} + +/** + Reads a 16-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciRead16 ( + IN UINTN Address + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciRead16 (Address)); +} + +/** + Writes a 16-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciWrite16 (Address, Value)); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciOr16 (Address, OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciAnd16 (Address, AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciAndThenOr16 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciBitFieldRead16 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciBitFieldWrite16 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port and saves the value + in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciBitFieldOr16 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciBitFieldAnd16 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 16-bit Address, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSavePciWrite16ValueToBootScript (Address, PciBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 32-bit PCI configuration value to the boot script. + + This internal worker function saves a 32-bit PCI configuration value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return Value. + +**/ +UINT32 +InternalSavePciWrite32ValueToBootScript ( + IN UINTN Address, + IN UINT32 Value + ) +{ + InternalSavePciWriteValueToBootScript (S3BootScriptWidthUint32, Address, &Value); + + return Value; +} + +/** + Reads a 32-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciRead32 ( + IN UINTN Address + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciRead32 (Address)); +} + +/** + Writes a 32-bit PCI configuration register and saves the value in the S3 + script to be replayed on S3 resume. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciWrite32 (Address, Value)); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciOr32 (Address, OrData)); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciAnd32 (Address, AndData)); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciAndThenOr32 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciBitFieldRead32 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciBitFieldWrite32 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port and saves the value + in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciBitFieldOr32 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciBitFieldAnd32 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 32-bit Address, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSavePciWrite32ValueToBootScript (Address, PciBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer + and saves the value in the S3 script to be replayed on S3 resume. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +S3PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint8, + PCILIB_TO_COMMON_ADDRESS (StartAddress), + PciReadBuffer (StartAddress, Size, Buffer), + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return Size; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space and saves the value in the S3 script to be replayed on S3 + resume. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +S3PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint8, + PCILIB_TO_COMMON_ADDRESS (StartAddress), + PciWriteBuffer (StartAddress, Size, Buffer), + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); + + return Size; +} diff --git a/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf new file mode 100644 index 000000000..c35a6c8f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf @@ -0,0 +1,39 @@ +## @file +# Instance of S3 PCI Segment Library based on PCI Segment and S3 BootScript Library. +# +# S3 PCI Segment Services that perform PCI Configuration cycles and +# also enable the PCI operation to be replayed during an S3 resume. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3PciSegmentLib + MODULE_UNI_FILE = BaseS3PciSegmentLib.uni + FILE_GUID = 17E2C90E-AD1F-443A-8C94-6E50C0E98607 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3PciSegmentLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + S3PciSegmentLib.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PciSegmentLib + S3BootScriptLib + DebugLib diff --git a/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni new file mode 100644 index 000000000..1fef46b33 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of S3 PCI Segment Library based on PCI Segment and S3 BootScript Library. +// +// S3 PCI Segment Services that perform PCI Configuration cycles and +// also enable the PCI operation to be replayed during an S3 resume. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of S3 PCI Segment Library based on PCI Segment and S3 BootScript Library." + +#string STR_MODULE_DESCRIPTION #language en-US "S3 PCI Segment Services that perform PCI Configuration cycles and also enable the PCI operation to be replayed during an S3 resume." + diff --git a/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c new file mode 100644 index 000000000..60d7ba24c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c @@ -0,0 +1,1243 @@ +/** @file + The multiple segments PCI configuration Library Services that carry out + PCI configuration and enable the PCI operations to be replayed during an + S3 resume. This library class maps directly on top of the PciSegmentLib class. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +/** + Macro that converts address in PciSegmentLib format to the new address that can be pass + to the S3 Boot Script Library functions. The Segment is dropped. + + @param Address Address in PciSegmentLib format. + + @retval New address that can be pass to the S3 Boot Script Library functions. +**/ +#define PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS(Address) \ + ((((UINT32)(Address) >> 20) & 0xff) << 24) | \ + ((((UINT32)(Address) >> 15) & 0x1f) << 16) | \ + ((((UINT32)(Address) >> 12) & 0x07) << 8) | \ + LShiftU64 ((Address) & 0xfff, 32) // Always put Register in high four bytes. + +/** + Saves a PCI configuration value to the boot script. + + This internal worker function saves a PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Width The width of PCI configuration. + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Buffer The buffer containing value. + +**/ +VOID +InternalSavePciSegmentWriteValueToBootScript ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfg2Write ( + Width, + RShiftU64 ((Address), 32) & 0xffff, + PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (Address), + 1, + Buffer + ); + ASSERT_RETURN_ERROR (Status); +} + +/** + Saves an 8-bit PCI configuration value to the boot script. + + This internal worker function saves an 8-bit PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT8 +InternalSavePciSegmentWrite8ValueToBootScript ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint8, Address, &Value); + + return Value; +} + +/** + Reads an 8-bit PCI configuration register, and saves the value in the S3 script to + be replayed on S3 resume. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +S3PciSegmentRead8 ( + IN UINT64 Address + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentRead8 (Address)); +} + +/** + Writes an 8-bit PCI configuration register, and saves the value in the S3 script to + be replayed on S3 resume. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentWrite8 (Address, Value)); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value, and saves + the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentOr8 (Address, OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentAnd8 (Address, AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise OR with another 8-bit value, and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentAndThenOr8 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldRead8 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register, and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldWrite8 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 8-bit port, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldOr8 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 8-bit register, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldAnd8 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, writes the result back to the bit field in the 8-bit port, + and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Saves a 16-bit PCI configuration value to the boot script. + + This internal worker function saves a 16-bit PCI configuration value in + the S3 script to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT16 +InternalSavePciSegmentWrite16ValueToBootScript ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint16, Address, &Value); + + return Value; +} + +/** + Reads a 16-bit PCI configuration register, and saves the value in the S3 script + to be replayed on S3 resume. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +S3PciSegmentRead16 ( + IN UINT64 Address + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentRead16 (Address)); +} + +/** + Writes a 16-bit PCI configuration register, and saves the value in the S3 script to + be replayed on S3 resume. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +S3PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentWrite16 (Address, Value)); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with a 16-bit + value, and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentOr16 (Address, OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentAnd16 (Address, AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise OR with another 16-bit value, and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentAndThenOr16 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldRead16 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register, and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldWrite16 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 16-bit port, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldOr16 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 16-bit register, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldAnd16 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, writes the result back to the bit field in the 16-bit port, + and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData)); +} + + + +/** + Saves a 32-bit PCI configuration value to the boot script. + + This internal worker function saves a 32-bit PCI configuration value in the S3 script + to be replayed on S3 resume. + + If the saving process fails, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value saved to boot script. + + @return Value. + +**/ +UINT32 +InternalSavePciSegmentWrite32ValueToBootScript ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint32, Address, &Value); + + return Value; +} + +/** + Reads a 32-bit PCI configuration register, and saves the value in the S3 script + to be replayed on S3 resume. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +S3PciSegmentRead32 ( + IN UINT64 Address + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentRead32 (Address)); +} + +/** + Writes a 32-bit PCI configuration register, and saves the value in the S3 script to + be replayed on S3 resume. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +S3PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentWrite32 (Address, Value)); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit + value, and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentOr32 (Address, OrData)); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentAnd32 (Address, AndData)); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise OR with another 32-bit value, and saves the value in the S3 script to + be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentAndThenOr32 (Address, AndData, OrData)); +} + +/** + Reads a bit field of a PCI configuration register, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldRead32 (Address, StartBit, EndBit)); +} + +/** + Writes a bit field to a PCI configuration register, and saves the value in + the S3 script to be replayed on S3 resume. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldWrite32 (Address, StartBit, EndBit, Value)); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 32-bit port, and saves the value in the + S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldOr32 (Address, StartBit, EndBit, OrData)); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register, and + saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldAnd32 (Address, StartBit, EndBit, AndData)); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, writes the result back to the bit field in the 32-bit port, + and saves the value in the S3 script to be replayed on S3 resume. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData)); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer, + and saves the value in the S3 script to be replayed on S3 resume. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +S3PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfg2Write ( + S3BootScriptWidthUint8, + RShiftU64 (StartAddress, 32) & 0xffff, + PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (StartAddress), + PciSegmentReadBuffer (StartAddress, Size, Buffer), + Buffer + ); + ASSERT_RETURN_ERROR (Status); + return Size; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space, and saves the value in the S3 script to be replayed on S3 + resume. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +S3PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSavePciCfg2Write ( + S3BootScriptWidthUint8, + RShiftU64 (StartAddress, 32) & 0xffff, + PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (StartAddress), + PciSegmentWriteBuffer (StartAddress, Size, Buffer), + Buffer + ); + ASSERT_RETURN_ERROR (Status); + return Size; +} diff --git a/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf new file mode 100644 index 000000000..db7a84396 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf @@ -0,0 +1,41 @@ +## @file +# Instance of S3 Smbus Library based on SmBus and S3 BootScript Library. +# +# S3 Smbus Library Services that do SMBus transactions and also enable the +# operatation to be replayed during an S3 resume. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3SmbusLib + MODULE_UNI_FILE = BaseS3SmbusLib.uni + FILE_GUID = 01190654-FED0-40d3-BA7F-2925539E5830 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3SmbusLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + S3SmbusLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + SmbusLib + S3BootScriptLib + diff --git a/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni new file mode 100644 index 000000000..b47990ca9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of S3 Smbus Library based on SmBus and S3 BootScript Library. +// +// S3 Smbus Library Services that do SMBus transactions and also enable the +// operatation to be replayed during an S3 resume. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of S3 SMBus Library based on SMBus and S3 BootScript Library" + +#string STR_MODULE_DESCRIPTION #language en-US "S3 SMBus Library Services that do SMBus transactions and also enable the operation to be replayed during an S3 resume." + diff --git a/roms/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c new file mode 100644 index 000000000..1a3c2bc82 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c @@ -0,0 +1,495 @@ +/** @file + Smbus Library Services that do SMBus transactions and also enable the operatation + to be replayed during an S3 resume. This library class maps directly on top + of the SmbusLib class. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +/** + Saves an SMBus operation to S3 script to be replayed on S3 resume. + + This function provides a standard way to save SMBus operation to S3 boot Script. + The data can either be of the Length byte, word, or a block of data. + If it falis to save S3 boot script, then ASSERT (). + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance that it will use to + execute the SMBus transactions. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. The maximum number of + bytes can be revision specific and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave device. Not all operations + require this argument. The length of this buffer is identified by Length. + +**/ +VOID +InternalSaveSmBusExecToBootScript ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN OUT VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSaveSmbusExecute ( + SmBusAddress, + SmbusOperation, + &Length, + Buffer + ); + ASSERT (Status == RETURN_SUCCESS); +} + +/** + Executes an SMBUS quick read command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID +EFIAPI +S3SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + SmBusQuickRead (SmBusAddress, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusQuickRead, SmBusAddress, 0, NULL); +} + +/** + Executes an SMBUS quick write command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID +EFIAPI +S3SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + SmBusQuickWrite (SmBusAddress, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusQuickWrite, SmBusAddress, 0, NULL); +} + +/** + Executes an SMBUS receive byte command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +S3SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + Byte = SmBusReceiveByte (SmBusAddress, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusReceiveByte, SmBusAddress, 1, &Byte); + + return Byte; +} + +/** + Executes an SMBUS send byte command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +S3SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + Byte = SmBusSendByte (SmBusAddress, Value, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusSendByte, SmBusAddress, 1, &Byte); + + return Byte; +} + +/** + Executes an SMBUS read data byte command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +S3SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + Byte = SmBusReadDataByte (SmBusAddress, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusReadByte, SmBusAddress, 1, &Byte); + + return Byte; +} + +/** + Executes an SMBUS write data byte command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +S3SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + Byte = SmBusWriteDataByte (SmBusAddress, Value, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusWriteByte, SmBusAddress, 1, &Byte); + + return Byte; +} + +/** + Executes an SMBUS read data word command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +S3SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + Word = SmBusReadDataWord (SmBusAddress, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusReadWord, SmBusAddress, 2, &Word); + + return Word; +} + +/** + Executes an SMBUS write data word command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +S3SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + Word = SmBusWriteDataWord (SmBusAddress, Value, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusWriteWord, SmBusAddress, 2, &Word); + + return Word; +} + +/** + Executes an SMBUS process call command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +S3SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + Word = SmBusProcessCall (SmBusAddress, Value, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusProcessCall, SmBusAddress, 2, &Value); + + return Word; +} + +/** + Executes an SMBUS read block command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +S3SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + Length = SmBusReadBlock (SmBusAddress, Buffer, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusReadBlock, SmBusAddress, Length, Buffer); + + return Length; +} + +/** + Executes an SMBUS write block command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +S3SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + Length = SmBusWriteBlock (SmBusAddress, Buffer, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusWriteBlock, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), Buffer); + + return Length; +} + +/** + Executes an SMBUS block process call command and saves the value in the S3 script to be replayed + on S3 resume. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +S3SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + Length = SmBusBlockProcessCall (SmBusAddress, WriteBuffer, ReadBuffer, Status); + + InternalSaveSmBusExecToBootScript (EfiSmbusBWBRProcessCall, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), ReadBuffer); + + return Length; +} diff --git a/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf b/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf new file mode 100644 index 000000000..ae0350921 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf @@ -0,0 +1,39 @@ +## @file +# Instance of S3 Stall Library based on Timer and S3 BootScript Library. +# +# Stall Services that do stall and also enable the Stall operatation +# to be replayed during an S3 resume. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseS3StallLib + MODULE_UNI_FILE = BaseS3StallLib.uni + FILE_GUID = 498C6AC3-CC29-4821-BE6F-7C6F4ECF2C14 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = S3StallLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + S3StallLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + TimerLib + S3BootScriptLib + diff --git a/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni b/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni new file mode 100644 index 000000000..40ee09f10 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of S3 Stall Library based on Timer and S3 BootScript Library. +// +// Stall Services that do stall and also enable the Stall operatation +// to be replayed during an S3 resume. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of S3 Stall Library based on Timer and S3 BootScript Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Stall Services that do stall and also enable the Stall operation to be replayed during an S3 resume." + diff --git a/roms/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c b/roms/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c new file mode 100644 index 000000000..f1f338844 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c @@ -0,0 +1,45 @@ +/** @file + Stall Services that do stall and also enable the Stall operatation + to be replayed during an S3 resume. This library class maps directly on top + of the Timer class. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + + +/** + Stalls the CPU for at least the given number of microseconds and and saves + the value in the S3 script to be replayed on S3 resume. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +S3Stall ( + IN UINTN MicroSeconds + ) +{ + RETURN_STATUS Status; + + Status = S3BootScriptSaveStall (MicroSecondDelay (MicroSeconds)); + ASSERT (Status == RETURN_SUCCESS); + + return MicroSeconds; +} + + diff --git a/roms/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf b/roms/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf new file mode 100644 index 000000000..40017ec88 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf @@ -0,0 +1,47 @@ +## @file +# Safe Integer Library +# +# This library provides helper functions to prevent integer overflow during +# type conversion, addition, subtraction, and multiplication. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2017, Microsoft Corporation +# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ +# +# All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseSafeIntLib + FILE_GUID = 4EA91BFA-3482-4930-B136-70679C6CE489 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SafeIntLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64 +# + +[Sources] + SafeIntLib.c + +[Sources.Ia32, Sources.ARM] + SafeIntLib32.c + +[Sources.X64, Sources.AARCH64, Sources.RISCV64] + SafeIntLib64.c + +[Sources.EBC] + SafeIntLibEbc.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c new file mode 100644 index 000000000..eec8ac1ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c @@ -0,0 +1,4148 @@ +/** @file + This library provides helper functions to prevent integer overflow during + type conversion, addition, subtraction, and multiplication. + + Copyright (c) 2017, Microsoft Corporation + + All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + + +// +// Magnitude of MIN_INT64 as expressed by a UINT64 number. +// +#define MIN_INT64_MAGNITUDE (((UINT64)(- (MIN_INT64 + 1))) + 1) + +// +// Conversion functions +// +// There are three reasons for having conversion functions: +// +// 1. We are converting from a signed type to an unsigned type of the same +// size, or vice-versa. +// +// 2. We are converting to a smaller type, and we could therefore possibly +// overflow. +// +// 3. We are converting to a bigger type, and we are signed and the type we are +// converting to is unsigned. +// + +/** + INT8 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToUint8 ( + IN INT8 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT8 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToChar8 ( + IN INT8 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT8 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToUint16 ( + IN INT8 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT8 -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToUint32 ( + IN INT8 Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT8 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToUintn ( + IN INT8 Operand, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINTN)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT8 -> UINT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8ToUint64 ( + IN INT8 Operand, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT8 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint8ToInt8 ( + IN UINT8 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT8 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint8ToChar8 ( + IN UINT8 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToInt8 ( + IN INT16 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToChar8 ( + IN INT16 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_INT8)) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToUint8 ( + IN INT16 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT8)) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToUint16 ( + IN INT16 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToUint32 ( + IN INT16 Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToUintn ( + IN INT16 Operand, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINTN)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT16 -> UINT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16ToUint64 ( + IN INT16 Operand, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16ToInt8 ( + IN UINT16 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16ToChar8 ( + IN UINT16 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16ToUint8 ( + IN UINT16 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT8) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16ToInt16 ( + IN UINT16 Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT16) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToInt8 ( + IN INT32 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToChar8 ( + IN INT32 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_INT8)) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUint8 ( + IN INT32 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT8)) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToInt16 ( + IN INT32 Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUint16 ( + IN INT32 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT16)) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUint32 ( + IN INT32 Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT32 -> UINT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUint64 ( + IN INT32 Operand, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToInt8 ( + IN UINT32 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToChar8 ( + IN UINT32 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToUint8 ( + IN UINT32 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT8) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToInt16 ( + IN UINT32 Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT16) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToUint16 ( + IN UINT32 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT16) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToInt32 ( + IN UINT32 Operand, + OUT INT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT32) { + *Result = (INT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToInt8 ( + IN INTN Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToChar8 ( + IN INTN Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_INT8)) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint8 ( + IN INTN Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT8)) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToInt16 ( + IN INTN Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint16 ( + IN INTN Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT16)) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUintn ( + IN INTN Operand, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINTN)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INTN -> UINT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint64 ( + IN INTN Operand, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt8 ( + IN UINTN Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToChar8 ( + IN UINTN Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToUint8 ( + IN UINTN Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT8) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt16 ( + IN UINTN Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT16) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToUint16 ( + IN UINTN Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT16) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt32 ( + IN UINTN Operand, + OUT INT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT32) { + *Result = (INT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToIntn ( + IN UINTN Operand, + OUT INTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INTN) { + *Result = (INTN)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToInt8 ( + IN INT64 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT8) && (Operand <= MAX_INT8)) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToChar8 ( + IN INT64 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_INT8)) { + *Result = (CHAR8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUint8 ( + IN INT64 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT8)) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToInt16 ( + IN INT64 Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT16) && (Operand <= MAX_INT16)) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUint16 ( + IN INT64 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT16)) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToInt32 ( + IN INT64 Operand, + OUT INT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= MIN_INT32) && (Operand <= MAX_INT32)) { + *Result = (INT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUint32 ( + IN INT64 Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Operand >= 0) && (Operand <= MAX_UINT32)) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + INT64 -> UINT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUint64 ( + IN INT64 Operand, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> INT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToInt8 ( + IN UINT64 Operand, + OUT INT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> CHAR8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToChar8 ( + IN UINT64 Operand, + OUT CHAR8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT8) { + *Result = (INT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = CHAR8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> UINT8 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUint8 ( + IN UINT64 Operand, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT8) { + *Result = (UINT8)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> INT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToInt16 ( + IN UINT64 Operand, + OUT INT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT16) { + *Result = (INT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> UINT16 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUint16 ( + IN UINT64 Operand, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT16) { + *Result = (UINT16)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToInt32 ( + IN UINT64 Operand, + OUT INT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT32) { + *Result = (INT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUint32 ( + IN UINT64 Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_UINT32) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToIntn ( + IN UINT64 Operand, + OUT INTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INTN) { + *Result = (INTN)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 -> INT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToInt64 ( + IN UINT64 Operand, + OUT INT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand <= MAX_INT64) { + *Result = (INT64)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = INT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +// +// Addition functions +// + +/** + UINT8 addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint8Add ( + IN UINT8 Augend, + IN UINT8 Addend, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (((UINT8)(Augend + Addend)) >= Augend) { + *Result = (UINT8)(Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16Add ( + IN UINT16 Augend, + IN UINT16 Addend, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (((UINT16)(Augend + Addend)) >= Augend) { + *Result = (UINT16)(Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32Add ( + IN UINT32 Augend, + IN UINT32 Addend, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Augend + Addend) >= Augend) { + *Result = (Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64Add ( + IN UINT64 Augend, + IN UINT64 Addend, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Augend + Addend) >= Augend) { + *Result = (Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +// +// Subtraction functions +// + +/** + UINT8 subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint8Sub ( + IN UINT8 Minuend, + IN UINT8 Subtrahend, + OUT UINT8 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Minuend >= Subtrahend) { + *Result = (UINT8)(Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT8_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT16 subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16Sub ( + IN UINT16 Minuend, + IN UINT16 Subtrahend, + OUT UINT16 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Minuend >= Subtrahend) { + *Result = (UINT16)(Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT16_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT32 subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32Sub ( + IN UINT32 Minuend, + IN UINT32 Subtrahend, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Minuend >= Subtrahend) { + *Result = (Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINT64 subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64Sub ( + IN UINT64 Minuend, + IN UINT64 Subtrahend, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Minuend >= Subtrahend) { + *Result = (Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +// +// Multiplication functions +// + +/** + UINT8 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint8Mult ( + IN UINT8 Multiplicand, + IN UINT8 Multiplier, + OUT UINT8 *Result + ) +{ + UINT32 IntermediateResult; + + IntermediateResult = ((UINT32)Multiplicand) *((UINT32)Multiplier); + + return SafeUint32ToUint8 (IntermediateResult, Result); +} + +/** + UINT16 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint16Mult ( + IN UINT16 Multiplicand, + IN UINT16 Multiplier, + OUT UINT16 *Result + ) +{ + UINT32 IntermediateResult; + + IntermediateResult = ((UINT32)Multiplicand) *((UINT32)Multiplier); + + return SafeUint32ToUint16 (IntermediateResult, Result); +} + +/** + UINT32 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32Mult ( + IN UINT32 Multiplicand, + IN UINT32 Multiplier, + OUT UINT32 *Result + ) +{ + UINT64 IntermediateResult; + + IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier); + + return SafeUint64ToUint32 (IntermediateResult, Result); +} + +/** + UINT64 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64Mult ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier, + OUT UINT64 *Result + ) +{ + RETURN_STATUS Status; + UINT32 DwordA; + UINT32 DwordB; + UINT32 DwordC; + UINT32 DwordD; + UINT64 ProductAD; + UINT64 ProductBC; + UINT64 ProductBD; + UINT64 UnsignedResult; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + ProductAD = 0; + ProductBC = 0; + ProductBD = 0; + UnsignedResult = 0; + Status = RETURN_BUFFER_TOO_SMALL; + + // + // 64x64 into 128 is like 32.32 x 32.32. + // + // a.b * c.d = a*(c.d) + .b*(c.d) = a*c + a*.d + .b*c + .b*.d + // back in non-decimal notation where A=a*2^32 and C=c*2^32: + // A*C + A*d + b*C + b*d + // So there are four components to add together. + // result = (a*c*2^64) + (a*d*2^32) + (b*c*2^32) + (b*d) + // + // a * c must be 0 or there would be bits in the high 64-bits + // a * d must be less than 2^32 or there would be bits in the high 64-bits + // b * c must be less than 2^32 or there would be bits in the high 64-bits + // then there must be no overflow of the resulting values summed up. + // + DwordA = (UINT32)RShiftU64 (Multiplicand, 32); + DwordC = (UINT32)RShiftU64 (Multiplier, 32); + + // + // common case -- if high dwords are both zero, no chance for overflow + // + if ((DwordA == 0) && (DwordC == 0)) { + DwordB = (UINT32)Multiplicand; + DwordD = (UINT32)Multiplier; + + *Result = (((UINT64)DwordB) *(UINT64)DwordD); + Status = RETURN_SUCCESS; + } else { + // + // a * c must be 0 or there would be bits set in the high 64-bits + // + if ((DwordA == 0) || + (DwordC == 0)) { + DwordD = (UINT32)Multiplier; + + // + // a * d must be less than 2^32 or there would be bits set in the high 64-bits + // + ProductAD = MultU64x64 ((UINT64)DwordA, (UINT64)DwordD); + if ((ProductAD & 0xffffffff00000000) == 0) { + DwordB = (UINT32)Multiplicand; + + // + // b * c must be less than 2^32 or there would be bits set in the high 64-bits + // + ProductBC = MultU64x64 ((UINT64)DwordB, (UINT64)DwordC); + if ((ProductBC & 0xffffffff00000000) == 0) { + // + // now sum them all up checking for overflow. + // shifting is safe because we already checked for overflow above + // + if (!RETURN_ERROR (SafeUint64Add (LShiftU64 (ProductBC, 32), LShiftU64 (ProductAD, 32), &UnsignedResult))) { + // + // b * d + // + ProductBD = MultU64x64 ((UINT64)DwordB, (UINT64)DwordD); + + if (!RETURN_ERROR (SafeUint64Add (UnsignedResult, ProductBD, &UnsignedResult))) { + *Result = UnsignedResult; + Status = RETURN_SUCCESS; + } + } + } + } + } + } + + if (RETURN_ERROR (Status)) { + *Result = UINT64_ERROR; + } + return Status; +} + +// +// Signed operations +// +// Strongly consider using unsigned numbers. +// +// Signed numbers are often used where unsigned numbers should be used. +// For example file sizes and array indices should always be unsigned. +// Subtracting a larger positive signed number from a smaller positive +// signed number with SafeInt32Sub will succeed, producing a negative number, +// that then must not be used as an array index (but can occasionally be +// used as a pointer index.) Similarly for adding a larger magnitude +// negative number to a smaller magnitude positive number. +// +// This library does not protect you from such errors. It tells you if your +// integer operations overflowed, not if you are doing the right thing +// with your non-overflowed integers. +// +// Likewise you can overflow a buffer with a non-overflowed unsigned index. +// + +// +// Signed addition functions +// + +/** + INT8 Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8Add ( + IN INT8 Augend, + IN INT8 Addend, + OUT INT8 *Result + ) +{ + return SafeInt32ToInt8 (((INT32)Augend) + ((INT32)Addend), Result); +} + +/** + CHAR8 Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeChar8Add ( + IN CHAR8 Augend, + IN CHAR8 Addend, + OUT CHAR8 *Result + ) +{ + INT32 Augend32; + INT32 Addend32; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + Augend32 = (INT32)Augend; + Addend32 = (INT32)Addend; + if (Augend32 < 0 || Augend32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + if (Addend32 < 0 || Addend32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + + return SafeInt32ToChar8 (Augend32 + Addend32, Result); +} + +/** + INT16 Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16Add ( + IN INT16 Augend, + IN INT16 Addend, + OUT INT16 *Result + ) +{ + return SafeInt32ToInt16 (((INT32)Augend) + ((INT32)Addend), Result); +} + +/** + INT32 Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32Add ( + IN INT32 Augend, + IN INT32 Addend, + OUT INT32 *Result + ) +{ + return SafeInt64ToInt32 (((INT64)Augend) + ((INT64)Addend), Result); +} + +/** + INT64 Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64Add ( + IN INT64 Augend, + IN INT64 Addend, + OUT INT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + // + // * An Addend of zero can never cause underflow or overflow. + // + // * A positive Addend can only cause overflow. The overflow condition is + // + // (Augend + Addend) > MAX_INT64 + // + // Subtracting Addend from both sides yields + // + // Augend > (MAX_INT64 - Addend) + // + // This condition can be coded directly in C because the RHS will neither + // underflow nor overflow. That is due to the starting condition: + // + // 0 < Addend <= MAX_INT64 + // + // Multiplying all three sides by (-1) yields + // + // 0 > (-Addend) >= (-MAX_INT64) + // + // Adding MAX_INT64 to all three sides yields + // + // MAX_INT64 > (MAX_INT64 - Addend) >= 0 + // + // * A negative Addend can only cause underflow. The underflow condition is + // + // (Augend + Addend) < MIN_INT64 + // + // Subtracting Addend from both sides yields + // + // Augend < (MIN_INT64 - Addend) + // + // This condition can be coded directly in C because the RHS will neither + // underflow nor overflow. That is due to the starting condition: + // + // MIN_INT64 <= Addend < 0 + // + // Multiplying all three sides by (-1) yields + // + // (-MIN_INT64) >= (-Addend) > 0 + // + // Adding MIN_INT64 to all three sides yields + // + // 0 >= (MIN_INT64 - Addend) > MIN_INT64 + // + if (((Addend > 0) && (Augend > (MAX_INT64 - Addend))) || + ((Addend < 0) && (Augend < (MIN_INT64 - Addend)))) { + *Result = INT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } else { + *Result = Augend + Addend; + Status = RETURN_SUCCESS; + } + + return Status; +} + +// +// Signed subtraction functions +// + +/** + INT8 Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8Sub ( + IN INT8 Minuend, + IN INT8 Subtrahend, + OUT INT8 *Result + ) +{ + return SafeInt32ToInt8 (((INT32)Minuend) - ((INT32)Subtrahend), Result); +} + +/** + CHAR8 Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeChar8Sub ( + IN CHAR8 Minuend, + IN CHAR8 Subtrahend, + OUT CHAR8 *Result + ) +{ + INT32 Minuend32; + INT32 Subtrahend32; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + Minuend32 = (INT32)Minuend; + Subtrahend32 = (INT32)Subtrahend; + if (Minuend32 < 0 || Minuend32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + if (Subtrahend32 < 0 || Subtrahend32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + + return SafeInt32ToChar8 (Minuend32 - Subtrahend32, Result); +} + +/** + INT16 Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16Sub ( + IN INT16 Minuend, + IN INT16 Subtrahend, + OUT INT16 *Result + ) +{ + return SafeInt32ToInt16 (((INT32)Minuend) - ((INT32)Subtrahend), Result); +} + +/** + INT32 Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32Sub ( + IN INT32 Minuend, + IN INT32 Subtrahend, + OUT INT32 *Result + ) +{ + return SafeInt64ToInt32 (((INT64)Minuend) - ((INT64)Subtrahend), Result); +} + +/** + INT64 Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64Sub ( + IN INT64 Minuend, + IN INT64 Subtrahend, + OUT INT64 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + // + // * A Subtrahend of zero can never cause underflow or overflow. + // + // * A positive Subtrahend can only cause underflow. The underflow condition + // is: + // + // (Minuend - Subtrahend) < MIN_INT64 + // + // Adding Subtrahend to both sides yields + // + // Minuend < (MIN_INT64 + Subtrahend) + // + // This condition can be coded directly in C because the RHS will neither + // underflow nor overflow. That is due to the starting condition: + // + // 0 < Subtrahend <= MAX_INT64 + // + // Adding MIN_INT64 to all three sides yields + // + // MIN_INT64 < (MIN_INT64 + Subtrahend) <= (MIN_INT64 + MAX_INT64) = -1 + // + // * A negative Subtrahend can only cause overflow. The overflow condition is + // + // (Minuend - Subtrahend) > MAX_INT64 + // + // Adding Subtrahend to both sides yields + // + // Minuend > (MAX_INT64 + Subtrahend) + // + // This condition can be coded directly in C because the RHS will neither + // underflow nor overflow. That is due to the starting condition: + // + // MIN_INT64 <= Subtrahend < 0 + // + // Adding MAX_INT64 to all three sides yields + // + // -1 = (MAX_INT64 + MIN_INT64) <= (MAX_INT64 + Subtrahend) < MAX_INT64 + // + if (((Subtrahend > 0) && (Minuend < (MIN_INT64 + Subtrahend))) || + ((Subtrahend < 0) && (Minuend > (MAX_INT64 + Subtrahend)))) { + *Result = INT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } else { + *Result = Minuend - Subtrahend; + Status = RETURN_SUCCESS; + } + + return Status; +} + +// +// Signed multiplication functions +// + +/** + INT8 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt8Mult ( + IN INT8 Multiplicand, + IN INT8 Multiplier, + OUT INT8 *Result + ) +{ + return SafeInt32ToInt8 (((INT32)Multiplier) *((INT32)Multiplicand), Result); +} + +/** + CHAR8 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to CHAR8_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeChar8Mult ( + IN CHAR8 Multiplicand, + IN CHAR8 Multiplier, + OUT CHAR8 *Result + ) +{ + INT32 Multiplicand32; + INT32 Multiplier32; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + Multiplicand32 = (INT32)Multiplicand; + Multiplier32 = (INT32)Multiplier; + if (Multiplicand32 < 0 || Multiplicand32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + if (Multiplier32 < 0 || Multiplier32 > MAX_INT8) { + *Result = CHAR8_ERROR; + return RETURN_BUFFER_TOO_SMALL; + } + + return SafeInt32ToChar8 (Multiplicand32 * Multiplier32, Result); +} + +/** + INT16 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT16_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt16Mult ( + IN INT16 Multiplicand, + IN INT16 Multiplier, + OUT INT16 *Result + ) +{ + return SafeInt32ToInt16 (((INT32)Multiplicand) *((INT32)Multiplier), Result); +} + +/** + INT32 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32Mult ( + IN INT32 Multiplicand, + IN INT32 Multiplier, + OUT INT32 *Result + ) +{ + return SafeInt64ToInt32 (MultS64x64 (Multiplicand, Multiplier), Result); +} + +/** + INT64 multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64Mult ( + IN INT64 Multiplicand, + IN INT64 Multiplier, + OUT INT64 *Result + ) +{ + RETURN_STATUS Status; + UINT64 UnsignedMultiplicand; + UINT64 UnsignedMultiplier; + UINT64 UnsignedResult; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + // + // Split into sign and magnitude, do unsigned operation, apply sign. + // + if (Multiplicand < 0) { + // + // Avoid negating the most negative number. + // + UnsignedMultiplicand = ((UINT64)(- (Multiplicand + 1))) + 1; + } else { + UnsignedMultiplicand = (UINT64)Multiplicand; + } + + if (Multiplier < 0) { + // + // Avoid negating the most negative number. + // + UnsignedMultiplier = ((UINT64)(- (Multiplier + 1))) + 1; + } else { + UnsignedMultiplier = (UINT64)Multiplier; + } + + Status = SafeUint64Mult (UnsignedMultiplicand, UnsignedMultiplier, &UnsignedResult); + if (!RETURN_ERROR (Status)) { + if ((Multiplicand < 0) != (Multiplier < 0)) { + if (UnsignedResult > MIN_INT64_MAGNITUDE) { + *Result = INT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } else if (UnsignedResult == MIN_INT64_MAGNITUDE) { + *Result = MIN_INT64; + } else { + *Result = - ((INT64)UnsignedResult); + } + } else { + if (UnsignedResult > MAX_INT64) { + *Result = INT64_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } else { + *Result = (INT64)UnsignedResult; + } + } + } else { + *Result = INT64_ERROR; + } + return Status; +} + diff --git a/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c new file mode 100644 index 000000000..39bf1c3c2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c @@ -0,0 +1,538 @@ +/** @file + This library provides helper functions to prevent integer overflow during + type conversion, addition, subtraction, and multiplication. + + Copyright (c) 2017, Microsoft Corporation + + All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + INT32 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUintn ( + IN INT32 Operand, + OUT UINTN *Result + ) +{ + return SafeInt32ToUint32 (Operand, (UINT32 *)Result); +} + +/** + UINT32 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToIntn ( + IN UINT32 Operand, + OUT INTN *Result + ) +{ + return SafeUint32ToInt32 (Operand, (INT32 *)Result); +} + +/** + INTN -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToInt32 ( + IN INTN Operand, + OUT INT32 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = (INT32)Operand; + return RETURN_SUCCESS; +} + +/** + INTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint32 ( + IN INTN Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Operand >= 0) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToUint32 ( + IN UINTN Operand, + OUT UINT32 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = (UINT32)Operand; + return RETURN_SUCCESS; +} + +/** + UINTN -> INT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt64 ( + IN UINTN Operand, + OUT INT64 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = (INT64)Operand; + return RETURN_SUCCESS; +} + +/** + INT64 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToIntn ( + IN INT64 Operand, + OUT INTN *Result + ) +{ + return SafeInt64ToInt32 (Operand, (INT32 *)Result); +} + +/** + INT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUintn ( + IN INT64 Operand, + OUT UINTN *Result + ) +{ + return SafeInt64ToUint32 (Operand, (UINT32 *)Result); +} + +/** + UINT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUintn ( + IN UINT64 Operand, + OUT UINTN *Result + ) +{ + return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result); +} + +/** + UINTN addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnAdd ( + IN UINTN Augend, + IN UINTN Addend, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((Augend + Addend) >= Augend) { + *Result = (Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnSub ( + IN UINTN Minuend, + IN UINTN Subtrahend, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (Minuend >= Subtrahend) { + *Result = (Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; +} + +/** + UINTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnMult ( + IN UINTN Multiplicand, + IN UINTN Multiplier, + OUT UINTN *Result + ) +{ + UINT64 IntermediateResult; + + IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier); + + return SafeUint64ToUintn (IntermediateResult, Result); +} + +/** + INTN Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnAdd ( + IN INTN Augend, + IN INTN Addend, + OUT INTN *Result + ) +{ + return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result); +} + +/** + INTN Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnSub ( + IN INTN Minuend, + IN INTN Subtrahend, + OUT INTN *Result + ) +{ + return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result); +} + +/** + INTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnMult ( + IN INTN Multiplicand, + IN INTN Multiplier, + OUT INTN *Result + ) +{ + return SafeInt64ToIntn (MultS64x64 (Multiplicand, Multiplier), Result); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c new file mode 100644 index 000000000..44e0a625a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c @@ -0,0 +1,491 @@ +/** @file + This library provides helper functions to prevent integer overflow during + type conversion, addition, subtraction, and multiplication. + + Copyright (c) 2017, Microsoft Corporation + + All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + INT32 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUintn ( + IN INT32 Operand, + OUT UINTN *Result + ) +{ + return SafeInt32ToUint64 (Operand, (UINT64 *) Result); +} + +/** + UINT32 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToIntn ( + IN UINT32 Operand, + OUT INTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = Operand; + return RETURN_SUCCESS; +} + +/** + INTN -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToInt32 ( + IN INTN Operand, + OUT INT32 *Result + ) +{ + return SafeInt64ToInt32 ((INT64) Operand, Result); +} + +/** + INTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint32 ( + IN INTN Operand, + OUT UINT32 *Result + ) +{ + return SafeInt64ToUint32 ((INT64)Operand, Result); +} + +/** + UINTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToUint32 ( + IN UINTN Operand, + OUT UINT32 *Result + ) +{ + return SafeUint64ToUint32 ((UINT64)Operand, Result); +} + +/** + UINTN -> INT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt64 ( + IN UINTN Operand, + OUT INT64 *Result + ) +{ + return SafeUint64ToInt64 ((UINT64)Operand, Result); +} + +/** + INT64 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToIntn ( + IN INT64 Operand, + OUT INTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = (INTN)Operand; + return RETURN_SUCCESS; +} + +/** + INT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUintn ( + IN INT64 Operand, + OUT UINTN *Result + ) +{ + return SafeInt64ToUint64 (Operand, (UINT64 *)Result); +} + +/** + UINT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUintn ( + IN UINT64 Operand, + OUT UINTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *Result = Operand; + return RETURN_SUCCESS; +} + +/** + UINTN addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnAdd ( + IN UINTN Augend, + IN UINTN Addend, + OUT UINTN *Result + ) +{ + return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result); +} + +/** + UINTN subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnSub ( + IN UINTN Minuend, + IN UINTN Subtrahend, + OUT UINTN *Result + ) +{ + return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result); +} + +/** + UINTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnMult ( + IN UINTN Multiplicand, + IN UINTN Multiplier, + OUT UINTN *Result + ) +{ + return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result); +} + +/** + INTN Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnAdd ( + IN INTN Augend, + IN INTN Addend, + OUT INTN *Result + ) +{ + return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result); +} + +/** + INTN Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnSub ( + IN INTN Minuend, + IN INTN Subtrahend, + OUT INTN *Result + ) +{ + return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result); +} + +/** + INTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnMult ( + IN INTN Multiplicand, + IN INTN Multiplier, + OUT INTN *Result + ) +{ + return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c new file mode 100644 index 000000000..de28bec97 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c @@ -0,0 +1,597 @@ +/** @file + This library provides helper functions to prevent integer overflow during + type conversion, addition, subtraction, and multiplication. + + Copyright (c) 2017, Microsoft Corporation + + All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + INT32 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt32ToUintn ( + IN INT32 Operand, + OUT UINTN *Result + ) +{ + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt32ToUint32 (Operand, (UINT32 *)Result); + } + return SafeInt32ToUint64 (Operand, (UINT64 *) Result); +} + +/** + UINT32 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint32ToIntn ( + IN UINT32 Operand, + OUT INTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeUint32ToInt32 (Operand, (INT32 *)Result); + } + *Result = Operand; + return RETURN_SUCCESS; +} + +/** + INTN -> INT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToInt32 ( + IN INTN Operand, + OUT INT32 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + *Result = (INT32)Operand; + return RETURN_SUCCESS; + } + return SafeInt64ToInt32 ((INT64) Operand, Result); +} + +/** + INTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnToUint32 ( + IN INTN Operand, + OUT UINT32 *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + if (Operand >= 0) { + *Result = (UINT32)Operand; + Status = RETURN_SUCCESS; + } else { + *Result = UINT32_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; + } + return SafeInt64ToUint32 ((INT64)Operand, Result); +} + +/** + UINTN -> UINT32 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToUint32 ( + IN UINTN Operand, + OUT UINT32 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + *Result = (UINT32)Operand; + return RETURN_SUCCESS; + } + return SafeUint64ToUint32 ((UINT64)Operand, Result); +} + +/** + UINTN -> INT64 conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnToInt64 ( + IN UINTN Operand, + OUT INT64 *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + *Result = (INT64)Operand; + return RETURN_SUCCESS; + } + return SafeUint64ToInt64 ((UINT64)Operand, Result); +} + +/** + INT64 -> INTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToIntn ( + IN INT64 Operand, + OUT INTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt64ToInt32 (Operand, (INT32 *)Result); + } + *Result = (INTN)Operand; + return RETURN_SUCCESS; +} + +/** + INT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeInt64ToUintn ( + IN INT64 Operand, + OUT UINTN *Result + ) +{ + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt64ToUint32 (Operand, (UINT32 *)Result); + } + return SafeInt64ToUint64 (Operand, (UINT64 *)Result); +} + +/** + UINT64 -> UINTN conversion + + Converts the value specified by Operand to a value specified by Result type + and stores the converted value into the caller allocated output buffer + specified by Result. The caller must pass in a Result buffer that is at + least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the conversion results in an overflow or an underflow condition, then + Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Operand Operand to be converted to new type + @param[out] Result Pointer to the result of conversion + + @retval RETURN_SUCCESS Successful conversion + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUint64ToUintn ( + IN UINT64 Operand, + OUT UINTN *Result + ) +{ + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result); + } + *Result = Operand; + return RETURN_SUCCESS; +} + +/** + UINTN addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnAdd ( + IN UINTN Augend, + IN UINTN Addend, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + if ((UINT32)(Augend + Addend) >= Augend) { + *Result = (Augend + Addend); + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; + } + return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result); +} + +/** + UINTN subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnSub ( + IN UINTN Minuend, + IN UINTN Subtrahend, + OUT UINTN *Result + ) +{ + RETURN_STATUS Status; + + if (Result == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if (sizeof (UINTN) == sizeof (UINT32)) { + if (Minuend >= Subtrahend) { + *Result = (Minuend - Subtrahend); + Status = RETURN_SUCCESS; + } else { + *Result = UINTN_ERROR; + Status = RETURN_BUFFER_TOO_SMALL; + } + + return Status; + } + return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result); +} + +/** + UINTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeUintnMult ( + IN UINTN Multiplicand, + IN UINTN Multiplier, + OUT UINTN *Result + ) +{ + UINT64 IntermediateResult; + + if (sizeof (UINTN) == sizeof (UINT32)) { + IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier); + + return SafeUint64ToUintn (IntermediateResult, Result); + } + return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result); +} + +/** + INTN Addition + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Augend A number to which addend will be added + @param[in] Addend A number to be added to another + @param[out] Result Pointer to the result of addition + + @retval RETURN_SUCCESS Successful addition + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnAdd ( + IN INTN Augend, + IN INTN Addend, + OUT INTN *Result + ) +{ + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result); + } + return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result); +} + +/** + INTN Subtraction + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Minuend A number from which another is to be subtracted. + @param[in] Subtrahend A number to be subtracted from another + @param[out] Result Pointer to the result of subtraction + + @retval RETURN_SUCCESS Successful subtraction + @retval RETURN_BUFFER_TOO_SMALL Underflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnSub ( + IN INTN Minuend, + IN INTN Subtrahend, + OUT INTN *Result + ) +{ + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result); + } + return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result); +} + +/** + INTN multiplication + + Performs the requested operation using the input parameters into a value + specified by Result type and stores the converted value into the caller + allocated output buffer specified by Result. The caller must pass in a + Result buffer that is at least as large as the Result type. + + If Result is NULL, RETURN_INVALID_PARAMETER is returned. + + If the requested operation results in an overflow or an underflow condition, + then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned. + + @param[in] Multiplicand A number that is to be multiplied by another + @param[in] Multiplier A number by which the multiplicand is to be multiplied + @param[out] Result Pointer to the result of multiplication + + @retval RETURN_SUCCESS Successful multiplication + @retval RETURN_BUFFER_TOO_SMALL Overflow + @retval RETURN_INVALID_PARAMETER Result is NULL +**/ +RETURN_STATUS +EFIAPI +SafeIntnMult ( + IN INTN Multiplicand, + IN INTN Multiplier, + OUT INTN *Result + ) +{ + if (sizeof (UINTN) == sizeof (UINT32)) { + return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result); + } + return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c new file mode 100644 index 000000000..4f70827f1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c @@ -0,0 +1,191 @@ +/** @file + Null Serial Port library instance with empty functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfully initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + return RETURN_SUCCESS; +} + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + If Buffer is NULL, then ASSERT(). + If NumberOfBytes is zero, then return 0. + + @param Buffer The pointer to the data buffer to be written. + @param NumberOfBytes The number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + + +/** + Read data from serial device and save the datas in buffer. + + Reads NumberOfBytes data bytes from a serial device into the buffer + specified by Buffer. The number of bytes actually read is returned. + If the return value is less than NumberOfBytes, then the rest operation failed. + If Buffer is NULL, then ASSERT(). + If NumberOfBytes is zero, then return 0. + + @param Buffer The pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes The number of bytes which will be read. + + @retval 0 Read data failed; No data is to be read. + @retval >0 The actual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls a serial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + return FALSE; +} + +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control signals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + return RETURN_UNSUPPORTED; +} + diff --git a/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf new file mode 100644 index 000000000..3d7b7ac31 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf @@ -0,0 +1,31 @@ +## @file +# Null instance of Serial Port Library with empty functions. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseSerialPortLibNull + MODULE_UNI_FILE = BaseSerialPortLibNull.uni + FILE_GUID = E4541241-8897-411a-91F8-7D7E45837146 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseSerialPortLibNull.c + + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni new file mode 100644 index 000000000..3108e7593 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Null instance of Serial Port Library with empty functions. +// +// Null instance of Serial Port Library with empty functions. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Null instance of Serial Port Library with empty functions" + +#string STR_MODULE_DESCRIPTION #language en-US "Null instance of Serial Port Library with empty functions." + diff --git a/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c new file mode 100644 index 000000000..42da5c0e6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c @@ -0,0 +1,538 @@ +/** @file +Null implementation of SmBusLib class library. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_UNSUPPORTED The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } +} + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_UNSUPPORTED The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } +} + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS The SMBUS command was executed. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + RETURN_DEVICE_ERROR The request was not completed because a failure + reflected in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (WriteBuffer != NULL); + ASSERT (ReadBuffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + if (Status != NULL) { + *Status = RETURN_UNSUPPORTED; + } + return 0; +} diff --git a/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf new file mode 100644 index 000000000..252b77cfd --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf @@ -0,0 +1,30 @@ +## @file +# Null implementation of the SMBUS Library. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseSmbusLibNull + MODULE_UNI_FILE = BaseSmbusLibNull.uni + FILE_GUID = E2ECA273-A1C0-407E-9A5C-F10C55142196 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmbusLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseSmbusLibNull.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib diff --git a/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni new file mode 100644 index 000000000..e57a45b66 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// Null implementation of the SMBUS Library. +// +// Null implementation of the SMBUS Library. +// +// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Null implementation of the SMBUS Library." + +#string STR_MODULE_DESCRIPTION #language en-US "Null implementation of the SMBUS Library." + diff --git a/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c new file mode 100644 index 000000000..d3efb8e46 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c @@ -0,0 +1,49 @@ +/** @file + Base Stack Check library for GCC/clang. + + Use -fstack-protector-all compiler flag to make the compiler insert the + __stack_chk_guard "canary" value into the stack and check the value prior + to exiting the function. If the "canary" is overwritten __stack_chk_fail() + is called. This is GCC specific code. + + Copyright (c) 2012, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +/// "canary" value that is inserted by the compiler into the stack frame. +VOID *__stack_chk_guard = (VOID*)0x0AFF; + +// If ASLR was enabled we could use +//void (*__stack_chk_guard)(void) = __stack_chk_fail; + +/** + Error path for compiler generated stack "canary" value check code. If the + stack canary has been overwritten this function gets called on exit of the + function. +**/ +VOID +__stack_chk_fail ( + VOID + ) +{ + UINT8 DebugPropertyMask; + + DEBUG ((DEBUG_ERROR, "STACK FAULT: Buffer Overflow in function %a.\n", __builtin_return_address(0))); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings even if + // BaseDebugLibNull is in use. + // + DebugPropertyMask = PcdGet8 (PcdDebugPropertyMask); + if ((DebugPropertyMask & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((DebugPropertyMask & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} diff --git a/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf new file mode 100644 index 000000000..0dc3c4a83 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf @@ -0,0 +1,40 @@ +## @file +# Stack Check Library +# +# Stack Check Library +# +# Copyright (c) 2014, ARM Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseStackCheckLib + MODULE_UNI_FILE = BaseStackCheckLib.uni + FILE_GUID = 5f6579f7-b648-4fdb-9f19-4c17e27e8eff + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + + +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + BaseStackCheckGcc.c | GCC + BaseStackCheckGcc.c | RVCT + BaseStackCheckNull.c | MSFT + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni new file mode 100644 index 000000000..03b9d7cd5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Stack Check Library +// +// Stack Check Library +// +// Copyright (c) 2014, ARM Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Stack Check Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Stack Check Library" + diff --git a/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c new file mode 100644 index 000000000..7032b78b3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c @@ -0,0 +1,9 @@ +/** @file + This file is purely empty as a work around for BaseStackCheck to pass MSVC build. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +extern int __BaseStackCheckNull; diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S new file mode 100644 index 000000000..1a0eb971a --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S @@ -0,0 +1,199 @@ +// Implementation of synchronization functions for ARM architecture (AArch64) +// +// Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +.text +.align 3 + +GCC_ASM_EXPORT(InternalSyncCompareExchange16) +GCC_ASM_EXPORT(InternalSyncCompareExchange32) +GCC_ASM_EXPORT(InternalSyncCompareExchange64) +GCC_ASM_EXPORT(InternalSyncIncrement) +GCC_ASM_EXPORT(InternalSyncDecrement) + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT16 +//EFIAPI +//InternalSyncCompareExchange16 ( +// IN volatile UINT16 *Value, +// IN UINT16 CompareValue, +// IN UINT16 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange16): + uxth w1, w1 + uxth w2, w2 + dmb sy + +InternalSyncCompareExchange16Again: + ldxrh w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange: + stxrh w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail: + dmb sy + mov w0, w3 + ret + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange32): + dmb sy + +InternalSyncCompareExchange32Again: + ldxr w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange: + stxr w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail: + dmb sy + mov w0, w3 + ret + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, +// IN UINT64 CompareValue, +// IN UINT64 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange64): + dmb sy + +InternalSyncCompareExchange64Again: + ldxr x3, [x0] + cmp x3, x1 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange: + stxr w4, x2, [x0] + cbnz w4, InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail: + dmb sy + mov x0, x3 + ret + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncIncrement): + dmb sy +TryInternalSyncIncrement: + ldxr w1, [x0] + add w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncIncrement + mov w0, w1 + dmb sy + ret + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncDecrement): + dmb sy +TryInternalSyncDecrement: + ldxr w1, [x0] + sub w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncDecrement + mov w0, w1 + dmb sy + ret diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm new file mode 100644 index 000000000..347de9a8b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm @@ -0,0 +1,199 @@ +; Implementation of synchronization functions for ARM architecture (AArch64) +; +; Copyright (c) 2012-2015, ARM Limited. All rights reserved. +; Copyright (c) 2015, Linaro Limited. All rights reserved. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; + + EXPORT InternalSyncCompareExchange16 + EXPORT InternalSyncCompareExchange32 + EXPORT InternalSyncCompareExchange64 + EXPORT InternalSyncIncrement + EXPORT InternalSyncDecrement + AREA BaseSynchronizationLib_LowLevel, CODE, READONLY + +;/** +; Performs an atomic compare exchange operation on a 16-bit unsigned integer. +; +; Performs an atomic compare exchange operation on the 16-bit unsigned integer +; specified by Value. If Value is equal to CompareValue, then Value is set to +; ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, +; then Value is returned. The compare exchange operation must be performed using +; MP safe mechanisms. +; +; @param Value A pointer to the 16-bit value for the compare exchange +; operation. +; @param CompareValue 16-bit value used in compare operation. +; @param ExchangeValue 16-bit value used in exchange operation. +; +; @return The original *Value before exchange. +; +;**/ +;UINT16 +;EFIAPI +;InternalSyncCompareExchange16 ( +; IN volatile UINT16 *Value, +; IN UINT16 CompareValue, +; IN UINT16 ExchangeValue +; ) +InternalSyncCompareExchange16 + uxth w1, w1 + uxth w2, w2 + dmb sy + +InternalSyncCompareExchange16Again + ldxrh w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange + stxrh w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail + dmb sy + mov w0, w3 + ret + +;/** +; Performs an atomic compare exchange operation on a 32-bit unsigned integer. +; +; Performs an atomic compare exchange operation on the 32-bit unsigned integer +; specified by Value. If Value is equal to CompareValue, then Value is set to +; ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, +; then Value is returned. The compare exchange operation must be performed using +; MP safe mechanisms. +; +; @param Value A pointer to the 32-bit value for the compare exchange +; operation. +; @param CompareValue 32-bit value used in compare operation. +; @param ExchangeValue 32-bit value used in exchange operation. +; +; @return The original *Value before exchange. +; +;**/ +;UINT32 +;EFIAPI +;InternalSyncCompareExchange32 ( +; IN volatile UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ) +InternalSyncCompareExchange32 + dmb sy + +InternalSyncCompareExchange32Again + ldxr w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange + stxr w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail + dmb sy + mov w0, w3 + ret + +;/** +; Performs an atomic compare exchange operation on a 64-bit unsigned integer. +; +; Performs an atomic compare exchange operation on the 64-bit unsigned integer specified +; by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and +; CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. +; The compare exchange operation must be performed using MP safe mechanisms. +; +; @param Value A pointer to the 64-bit value for the compare exchange +; operation. +; @param CompareValue 64-bit value used in compare operation. +; @param ExchangeValue 64-bit value used in exchange operation. +; +; @return The original *Value before exchange. +; +;**/ +;UINT64 +;EFIAPI +;InternalSyncCompareExchange64 ( +; IN volatile UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ) +InternalSyncCompareExchange64 + dmb sy + +InternalSyncCompareExchange64Again + ldxr x3, [x0] + cmp x3, x1 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange + stxr w4, x2, [x0] + cbnz w4, InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail + dmb sy + mov x0, x3 + ret + +;/** +; Performs an atomic increment of an 32-bit unsigned integer. +; +; Performs an atomic increment of the 32-bit unsigned integer specified by +; Value and returns the incremented value. The increment operation must be +; performed using MP safe mechanisms. The state of the return value is not +; guaranteed to be MP safe. +; +; @param Value A pointer to the 32-bit value to increment. +; +; @return The incremented value. +; +;**/ +;UINT32 +;EFIAPI +;InternalSyncIncrement ( +; IN volatile UINT32 *Value +; ) +InternalSyncIncrement + dmb sy +TryInternalSyncIncrement + ldxr w1, [x0] + add w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncIncrement + mov w0, w1 + dmb sy + ret + +;/** +; Performs an atomic decrement of an 32-bit unsigned integer. +; +; Performs an atomic decrement of the 32-bit unsigned integer specified by +; Value and returns the decrement value. The decrement operation must be +; performed using MP safe mechanisms. The state of the return value is not +; guaranteed to be MP safe. +; +; @param Value A pointer to the 32-bit value to decrement. +; +; @return The decrement value. +; +;**/ +;UINT32 +;EFIAPI +;InternalSyncDecrement ( +; IN volatile UINT32 *Value +; ) +InternalSyncDecrement + dmb sy +TryInternalSyncDecrement + ldxr w1, [x0] + sub w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncDecrement + mov w0, w1 + dmb sy + ret + + END diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S new file mode 100644 index 000000000..607a1697b --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S @@ -0,0 +1,207 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +.text +.align 3 + +GCC_ASM_EXPORT(InternalSyncCompareExchange16) +GCC_ASM_EXPORT(InternalSyncCompareExchange32) +GCC_ASM_EXPORT(InternalSyncCompareExchange64) +GCC_ASM_EXPORT(InternalSyncIncrement) +GCC_ASM_EXPORT(InternalSyncDecrement) + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT16 +//EFIAPI +//InternalSyncCompareExchange16 ( +// IN volatile UINT16 *Value, +// IN UINT16 CompareValue, +// IN UINT16 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange16): + dmb + +InternalSyncCompareExchange16Again: + ldrexh r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange: + strexh ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail: + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange32): + dmb + +InternalSyncCompareExchange32Again: + ldrex r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange: + strex ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail: + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, // r0 +// IN UINT64 CompareValue, // r2-r3 +// IN UINT64 ExchangeValue // stack +// ) +ASM_PFX(InternalSyncCompareExchange64): + push { r4-r7 } + ldrd r4, r5, [sp, #16] + dmb + +InternalSyncCompareExchange64Again: + ldrexd r6, r7, [r0] + cmp r6, r2 + cmpeq r7, r3 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange: + strexd ip, r4, r5, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail: + dmb + mov r0, r6 + mov r1, r7 + pop { r4-r7 } + bx lr + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncIncrement): + dmb +TryInternalSyncIncrement: + ldrex r1, [r0] + add r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncIncrement + dmb + mov r0, r1 + bx lr + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncDecrement): + dmb +TryInternalSyncDecrement: + ldrex r1, [r0] + sub r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncDecrement + dmb + mov r0, r1 + bx lr diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm new file mode 100644 index 000000000..920b373e2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm @@ -0,0 +1,208 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + + EXPORT InternalSyncCompareExchange16 + EXPORT InternalSyncCompareExchange32 + EXPORT InternalSyncCompareExchange64 + EXPORT InternalSyncIncrement + EXPORT InternalSyncDecrement + + AREA ArmSynchronization, CODE, READONLY + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT16 +//EFIAPI +//InternalSyncCompareExchange16 ( +// IN volatile UINT16 *Value, +// IN UINT16 CompareValue, +// IN UINT16 ExchangeValue +// ) +InternalSyncCompareExchange16 + dmb + +InternalSyncCompareExchange16Again + ldrexh r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange + strexh ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +InternalSyncCompareExchange32 + dmb + +InternalSyncCompareExchange32Again + ldrex r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange + strex ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, // r0 +// IN UINT64 CompareValue, // r2-r3 +// IN UINT64 ExchangeValue // stack +// ) +InternalSyncCompareExchange64 + push { r4-r7 } + ldrd r4, r5, [sp, #16] + dmb + +InternalSyncCompareExchange64Again + ldrexd r6, r7, [r0] + cmp r6, r2 + cmpeq r7, r3 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange + strexd ip, r4, r5, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail + dmb + mov r0, r6 + mov r1, r7 + pop { r4-r7 } + bx lr + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +InternalSyncIncrement + dmb +TryInternalSyncIncrement + ldrex r1, [r0] + add r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncIncrement + dmb + mov r0, r1 + bx lr + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +InternalSyncDecrement + dmb +TryInternalSyncDecrement + ldrex r1, [r0] + sub r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncDecrement + dmb + mov r0, r1 + bx lr + + END diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf new file mode 100755 index 000000000..83d5b8ed7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf @@ -0,0 +1,97 @@ +## @file +# Base Synchronization Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseSynchronizationLib + MODULE_UNI_FILE = BaseSynchronizationLib.uni + FILE_GUID = FC9990DF-C5FF-44cf-8799-CBB45B577F87 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SynchronizationLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 +# +[Sources] + BaseSynchronizationLibInternals.h + +[Sources.IA32] + Ia32/InternalGetSpinLockProperties.c | MSFT + Ia32/InterlockedCompareExchange64.c | MSFT + Ia32/InterlockedCompareExchange32.c | MSFT + Ia32/InterlockedCompareExchange16.c | MSFT + InterlockedIncrementMsc.c | MSFT + InterlockedDecrementMsc.c | MSFT + SynchronizationMsc.c | MSFT + + Ia32/InterlockedCompareExchange64.nasm| INTEL + Ia32/InterlockedCompareExchange32.nasm| INTEL + Ia32/InterlockedCompareExchange16.nasm| INTEL + Ia32/InterlockedDecrement.nasm| INTEL + Ia32/InterlockedIncrement.nasm| INTEL + Synchronization.c | INTEL + + Ia32/InternalGetSpinLockProperties.c | GCC + Ia32/GccInline.c | GCC + SynchronizationGcc.c | GCC + +[Sources.X64] + Ia32/InternalGetSpinLockProperties.c | MSFT + X64/InterlockedCompareExchange64.c | MSFT + X64/InterlockedCompareExchange32.c | MSFT + X64/InterlockedCompareExchange16.c | MSFT + InterlockedIncrementMsc.c | MSFT + InterlockedDecrementMsc.c | MSFT + SynchronizationMsc.c | MSFT + + X64/InterlockedCompareExchange64.nasm| INTEL + X64/InterlockedCompareExchange32.nasm| INTEL + X64/InterlockedCompareExchange16.nasm| INTEL + X64/InterlockedDecrement.nasm | INTEL + X64/InterlockedIncrement.nasm | INTEL + Synchronization.c | INTEL + + Ia32/InternalGetSpinLockProperties.c | GCC + X64/GccInline.c | GCC + SynchronizationGcc.c | GCC + +[Sources.EBC] + Synchronization.c + Ebc/Synchronization.c + +[Sources.ARM] + Synchronization.c + Arm/Synchronization.asm | RVCT + Arm/Synchronization.S | GCC + +[Sources.AARCH64] + Synchronization.c + AArch64/Synchronization.S | GCC + AArch64/Synchronization.asm | MSFT + +[Sources.RISCV64] + Synchronization.c + RiscV64/Synchronization.S + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + TimerLib + DebugLib + BaseMemoryLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout ## SOMETIMES_CONSUMES + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni new file mode 100644 index 000000000..cae971f34 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Base Synchronization Library implementation. +// +// Base Synchronization Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Base Synchronization Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Synchronization Library implementation." + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h new file mode 100644 index 000000000..4e2bcbc6c --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h @@ -0,0 +1,145 @@ +/** @file + Declaration of internal functions in BaseSynchronizationLib. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_SYNCHRONIZATION_LIB_INTERNALS__ +#define __BASE_SYNCHRONIZATION_LIB_INTERNALS__ + +#include +#include +#include +#include +#include +#include + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ); + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ); + + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue A 16-bit value used in compare operation. + @param ExchangeValue A 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ); + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in compare operation. + @param ExchangeValue A 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ); + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in compare operation. + @param ExchangeValue A 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ); + +/** + Internal function to retrieve the architecture specific spin lock alignment + requirements for optimal spin lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +InternalGetSpinLockProperties ( + VOID + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c new file mode 100644 index 000000000..a45f509e6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c @@ -0,0 +1,141 @@ +/** @file + Implementation of synchronization functions on EBC. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Performs an atomic compare exchange operation on a 16-bit + unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit + unsigned integer specified by Value. If Value is equal to + CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange + operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the + compare exchange operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + return *Value != CompareValue ? *Value : + ((*Value = ExchangeValue), CompareValue); +} + +/** + Performs an atomic compare exchange operation on a 32-bit + unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit + unsigned integer specified by Value. If Value is equal to + CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange + operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the + compare exchange operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + return *Value != CompareValue ? *Value : + ((*Value = ExchangeValue), CompareValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + return *Value != CompareValue ? *Value : + ((*Value = ExchangeValue), CompareValue); +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + return ++*Value; +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + return --*Value; +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c new file mode 100644 index 000000000..1d1528745 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c @@ -0,0 +1,201 @@ +/** @file + GCC inline implementation of BaseSynchronizationLib processor specific functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "movl $1, %%eax \n\t" + "lock \n\t" + "xadd %%eax, %1 \n\t" + "inc %%eax \n\t" + : "=&a" (Result), // %0 + "+m" (*Value) // %1 + : // no inputs that aren't also outputs + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "movl $-1, %%eax \n\t" + "lock \n\t" + "xadd %%eax, %1 \n\t" + "dec %%eax \n\t" + : "=&a" (Result), // %0 + "+m" (*Value) // %1 + : // no inputs that aren't also outputs + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgw %2, %1 \n\t" + : "+a" (CompareValue), // %0 + "+m" (*Value) // %1 + : "q" (ExchangeValue) // %2 + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgl %2, %1 \n\t" + : "+a" (CompareValue), // %0 + "+m" (*Value) // %1 + : "q" (ExchangeValue) // %2 + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchg8b (%1) \n\t" + : "+A" (CompareValue) // %0 + : "S" (Value), // %1 + "b" ((UINT32) ExchangeValue), // %2 + "c" ((UINT32) (ExchangeValue >> 32)) // %3 + : "memory", + "cc" + ); + + return CompareValue; +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c new file mode 100644 index 000000000..fef9d3bf5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c @@ -0,0 +1,45 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + _asm { + mov ecx, Value + mov ax, CompareValue + mov dx, ExchangeValue + lock cmpxchg [ecx], dx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm new file mode 100644 index 000000000..36bed4d72 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange16.Asm +; +; Abstract: +; +; InterlockedCompareExchange16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; InternalSyncCompareExchange16 ( +; IN volatile UINT16 *Value, +; IN UINT16 CompareValue, +; IN UINT16 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange16) +ASM_PFX(InternalSyncCompareExchange16): + mov ecx, [esp + 4] + mov ax, [esp + 8] + mov dx, [esp + 12] + lock cmpxchg [ecx], dx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c new file mode 100644 index 000000000..1aa1c8eee --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c @@ -0,0 +1,44 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + _asm { + mov ecx, Value + mov eax, CompareValue + mov edx, ExchangeValue + lock cmpxchg [ecx], edx + } +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm new file mode 100644 index 000000000..2591418e4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncCompareExchange32 ( +; IN volatile UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange32) +ASM_PFX(InternalSyncCompareExchange32): + mov ecx, [esp + 4] + mov eax, [esp + 8] + mov edx, [esp + 12] + lock cmpxchg [ecx], edx + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c new file mode 100644 index 000000000..33cb2a047 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c @@ -0,0 +1,44 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + _asm { + mov esi, Value + mov eax, dword ptr [CompareValue + 0] + mov edx, dword ptr [CompareValue + 4] + mov ebx, dword ptr [ExchangeValue + 0] + mov ecx, dword ptr [ExchangeValue + 4] + lock cmpxchg8b qword ptr [esi] + } +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm new file mode 100644 index 000000000..209c41ddf --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalSyncCompareExchange64 ( +; IN volatile UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange64) +ASM_PFX(InternalSyncCompareExchange64): + push esi + push ebx + mov esi, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov ebx, [esp + 24] + mov ecx, [esp + 28] + lock cmpxchg8b [esi] + pop ebx + pop esi + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm new file mode 100644 index 000000000..4a2587288 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncDecrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncDecrement) +ASM_PFX(InternalSyncDecrement): + mov ecx, [esp + 4] + mov eax, 0FFFFFFFFh + lock xadd dword [ecx], eax + dec eax + ret diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm new file mode 100644 index 000000000..afa5ad2cc --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncIncrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncIncrement) +ASM_PFX(InternalSyncIncrement): + mov ecx, [esp + 4] + mov eax, 1 + lock xadd dword [ecx], eax + inc eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c new file mode 100644 index 000000000..3e270a171 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c @@ -0,0 +1,58 @@ +/** @file + Internal function to get spin lock alignment. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +/** + Internal function to retrieve the architecture specific spin lock alignment + requirements for optimal spin lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +InternalGetSpinLockProperties ( + VOID + ) +{ + UINT32 RegEax; + UINT32 RegEbx; + UINTN FamilyId; + UINTN ModelId; + UINTN CacheLineSize; + + // + // Retrieve CPUID Version Information + // + AsmCpuid (0x01, &RegEax, &RegEbx, NULL, NULL); + // + // EBX: Bits 15 - 08: CLFLUSH line size (Value * 8 = cache line size) + // + CacheLineSize = ((RegEbx >> 8) & 0xff) * 8; + // + // Retrieve CPU Family and Model + // + FamilyId = (RegEax >> 8) & 0xf; + ModelId = (RegEax >> 4) & 0xf; + if (FamilyId == 0x0f) { + // + // In processors based on Intel NetBurst microarchitecture, use two cache lines + // + ModelId = ModelId | ((RegEax >> 12) & 0xf0); + if (ModelId <= 0x04 || ModelId == 0x06) { + CacheLineSize *= 2; + } + } + + if (CacheLineSize < 32) { + CacheLineSize = 32; + } + + return CacheLineSize; +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c new file mode 100644 index 000000000..7317bc2a9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c @@ -0,0 +1,40 @@ +/** @file + InterlockedDecrement function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedDecrement( + long * lpAddend +); + +#pragma intrinsic(_InterlockedDecrement) + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + return _InterlockedDecrement ((long *)(Value)); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c new file mode 100644 index 000000000..bb51ec56d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c @@ -0,0 +1,40 @@ +/** @file + InterLockedIncrement function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedIncrement( + long * lpAddend +); + +#pragma intrinsic(_InterlockedIncrement) + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + return _InterlockedIncrement ((long *)(Value)); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/RiscV64/Synchronization.S b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/RiscV64/Synchronization.S new file mode 100644 index 000000000..bac80d687 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/RiscV64/Synchronization.S @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// +// RISC-V synchronization functions. +// +// Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//------------------------------------------------------------------------------ +#include + +.data + +.text +.align 3 + +.global ASM_PFX(InternalSyncCompareExchange32) +.global ASM_PFX(InternalSyncCompareExchange64) +.global ASM_PFX(InternalSyncIncrement) +.global ASM_PFX(InternalSyncDecrement) + +// +// ompare and xchange a 32-bit value. +// +// @param a0 : Pointer to 32-bit value. +// @param a1 : Compare value. +// @param a2 : Exchange value. +// +ASM_PFX (InternalSyncCompareExchange32): + lr.w a3, (a0) // Load the value from a0 and make + // the reservation of address. + bne a3, a1, exit + sc.w a3, a2, (a0) // Write the value back to the address. + mv a3, a1 +exit: + mv a0, a3 + ret + +.global ASM_PFX(InternalSyncCompareExchange64) + +// +// Compare and xchange a 64-bit value. +// +// @param a0 : Pointer to 64-bit value. +// @param a1 : Compare value. +// @param a2 : Exchange value. +// +ASM_PFX (SyncCompareExchange64): + lr.d a3, (a0) // Load the value from a0 and make + // the reservation of address. + bne a3, a1, exit + sc.d a3, a2, (a0) // Write the value back to the address. + mv a3, a1 +exit2: + mv a0, a3 + ret + +// +// Performs an atomic increment of an 32-bit unsigned integer. +// +// @param a0 : Pointer to 32-bit value. +// +ASM_PFX (InternalSyncIncrement): + li a1, 1 + amoadd.w a2, a1, (a0) + mv a0, a2 + ret + +// +// Performs an atomic decrement of an 32-bit unsigned integer. +// +// @param a0 : Pointer to 32-bit value. +// +ASM_PFX (InternalSyncDecrement): + li a1, -1 + amoadd.w a2, a1, (a0) + mv a0, a2 + ret diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c new file mode 100644 index 000000000..3f7a0c7af --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c @@ -0,0 +1,410 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment is byte alignment. + It must be a power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return 32; +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + *SpinLock = SPIN_LOCK_RELEASED; + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; + + if (PcdGet32 (PcdSpinLockTimeout) == 0) { + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + } else if (!AcquireSpinLockOrFail (SpinLock)) { + // + // Get the current timer value + // + Current = GetPerformanceCounter(); + + // + // Initialize local variables + // + Start = 0; + End = 0; + Total = 0; + + // + // Retrieve the performance counter properties and compute the number of performance + // counter ticks required to reach the timeout + // + Timeout = DivU64x32 ( + MultU64x32 ( + GetPerformanceCounterProperties (&Start, &End), + PcdGet32 (PcdSpinLockTimeout) + ), + 1000000 + ); + Cycle = End - Start; + if (Cycle < 0) { + Cycle = -Cycle; + } + Cycle++; + + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + Previous = Current; + Current = GetPerformanceCounter(); + Delta = (INT64) (Current - Previous); + if (Start > End) { + Delta = -Delta; + } + if (Delta < 0) { + Delta += Cycle; + } + Total += Delta; + ASSERT (Total < Timeout); + } + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue); + + return (BOOLEAN)( + InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ) == (VOID*)SPIN_LOCK_RELEASED + ); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue); + + *SpinLock = SPIN_LOCK_RELEASED; + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InterlockedCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue Pointer value used in compare operation. + @param ExchangeValue Pointer value used in exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32 *)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64 *)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c new file mode 100644 index 000000000..466775e60 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c @@ -0,0 +1,426 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +// +// GCC inline assembly for Read Write Barrier +// +#define _ReadWriteBarrier() do { __asm__ __volatile__ ("": : : "memory"); } while(0) + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment is byte alignment. + It must be a power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return InternalGetSpinLockProperties (); +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + + _ReadWriteBarrier(); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier(); + + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; + + if (PcdGet32 (PcdSpinLockTimeout) == 0) { + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + } else if (!AcquireSpinLockOrFail (SpinLock)) { + // + // Get the current timer value + // + Current = GetPerformanceCounter(); + + // + // Initialize local variables + // + Start = 0; + End = 0; + Total = 0; + + // + // Retrieve the performance counter properties and compute the number of performance + // counter ticks required to reach the timeout + // + Timeout = DivU64x32 ( + MultU64x32 ( + GetPerformanceCounterProperties (&Start, &End), + PcdGet32 (PcdSpinLockTimeout) + ), + 1000000 + ); + Cycle = End - Start; + if (Cycle < 0) { + Cycle = -Cycle; + } + Cycle++; + + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + Previous = Current; + Current = GetPerformanceCounter(); + Delta = (INT64) (Current - Previous); + if (Start > End) { + Delta = -Delta; + } + if (Delta < 0) { + Delta += Cycle; + } + Total += Delta; + ASSERT (Total < Timeout); + } + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + VOID *Result; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + Result = InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ); + + _ReadWriteBarrier (); + return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released the lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier (); + + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue A 16-bit value used in compare operation. + @param ExchangeValue A 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InterlockedCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in compare operation. + @param ExchangeValue A 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue A pointer value used in a compare operation. + @param ExchangeValue A pointer value used in an exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32 *)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64 *)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c new file mode 100644 index 000000000..12b01ff89 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c @@ -0,0 +1,428 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +/** + Microsoft Visual Studio 7.1 Function Prototypes for read write barrier Intrinsics. +**/ + +void _ReadWriteBarrier (void); +#pragma intrinsic(_ReadWriteBarrier) + + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment is byte alignment. + It must be a power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return InternalGetSpinLockProperties (); +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + + _ReadWriteBarrier(); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier(); + + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; + + if (PcdGet32 (PcdSpinLockTimeout) == 0) { + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + } else if (!AcquireSpinLockOrFail (SpinLock)) { + // + // Get the current timer value + // + Current = GetPerformanceCounter(); + + // + // Initialize local variables + // + Start = 0; + End = 0; + Total = 0; + + // + // Retrieve the performance counter properties and compute the number of performance + // counter ticks required to reach the timeout + // + Timeout = DivU64x32 ( + MultU64x32 ( + GetPerformanceCounterProperties (&Start, &End), + PcdGet32 (PcdSpinLockTimeout) + ), + 1000000 + ); + Cycle = End - Start; + if (Cycle < 0) { + Cycle = -Cycle; + } + Cycle++; + + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + Previous = Current; + Current = GetPerformanceCounter(); + Delta = (INT64) (Current - Previous); + if (Start > End) { + Delta = -Delta; + } + if (Delta < 0) { + Delta += Cycle; + } + Total += Delta; + ASSERT (Total < Timeout); + } + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + VOID *Result; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + Result = InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ); + + _ReadWriteBarrier (); + return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released the lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier (); + + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue A 16-bit value used in a compare operation. + @param ExchangeValue A 16-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InterlockedCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in a compare operation. + @param ExchangeValue A 32-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue A pointer value used in a compare operation. + @param ExchangeValue A pointer value used in an exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = (UINT8) sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32*)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64*)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c new file mode 100644 index 000000000..be19219c2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c @@ -0,0 +1,200 @@ +/** @file + GCC inline implementation of BaseSynchronizationLib processor specific functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "movl $1, %%eax \n\t" + "lock \n\t" + "xadd %%eax, %1 \n\t" + "inc %%eax \n\t" + : "=&a" (Result), // %0 + "+m" (*Value) // %1 + : // no inputs that aren't also outputs + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "movl $-1, %%eax \n\t" + "lock \n\t" + "xadd %%eax, %1 \n\t" + "dec %%eax \n\t" + : "=&a" (Result), // %0 + "+m" (*Value) // %1 + : // no inputs that aren't also outputs + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgw %2, %1 \n\t" + : "+a" (CompareValue), // %0 + "+m" (*Value) // %1 + : "r" (ExchangeValue) // %2 + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgl %2, %1 \n\t" + : "+a" (CompareValue), // %0 + "+m" (*Value) // %1 + : "r" (ExchangeValue) // %2 + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgq %2, %1 \n\t" + : "+a" (CompareValue), // %0 + "+m" (*Value) // %1 + : "r" (ExchangeValue) // %2 + : "memory", + "cc" + ); + + return CompareValue; +} diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c new file mode 100644 index 000000000..4bbf190d5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c @@ -0,0 +1,48 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +__int16 _InterlockedCompareExchange16( + __int16 volatile * Destination, + __int16 Exchange, + __int16 Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange16) + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm new file mode 100644 index 000000000..81a243231 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange16.Asm +; +; Abstract: +; +; InterlockedCompareExchange16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; InternalSyncCompareExchange16 ( +; IN volatile UINT16 *Value, +; IN UINT16 CompareValue, +; IN UINT16 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange16) +ASM_PFX(InternalSyncCompareExchange16): + mov ax, dx + lock cmpxchg [rcx], r8w + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c new file mode 100644 index 000000000..c693a0640 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c @@ -0,0 +1,48 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedCompareExchange( + long volatile * Destination, + long Exchange, + long Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange) + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + return _InterlockedCompareExchange (Value, ExchangeValue, CompareValue); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm new file mode 100644 index 000000000..f914f6264 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncCompareExchange32 ( +; IN volatile UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange32) +ASM_PFX(InternalSyncCompareExchange32): + mov eax, edx + lock cmpxchg [rcx], r8d + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c new file mode 100644 index 000000000..4b9167c0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c @@ -0,0 +1,47 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +__int64 _InterlockedCompareExchange64( + __int64 volatile * Destination, + __int64 Exchange, + __int64 Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange64) + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + return _InterlockedCompareExchange64 (Value, ExchangeValue, CompareValue); +} + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm new file mode 100644 index 000000000..4bee1e485 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalSyncCompareExchange64 ( +; IN volatile UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncCompareExchange64) +ASM_PFX(InternalSyncCompareExchange64): + mov rax, rdx + lock cmpxchg [rcx], r8 + ret + diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm new file mode 100644 index 000000000..945043da9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncDecrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncDecrement) +ASM_PFX(InternalSyncDecrement): + mov eax, 0FFFFFFFFh + lock xadd dword [rcx], eax + dec eax + ret diff --git a/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm new file mode 100644 index 000000000..3b650a169 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncIncrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalSyncIncrement) +ASM_PFX(InternalSyncIncrement): + mov eax, 1 + lock xadd dword [rcx], eax + inc eax + ret + diff --git a/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf new file mode 100644 index 000000000..aa6919af9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf @@ -0,0 +1,40 @@ +## @file +# NULL instance of Timer Library as a template. +# +# A non-functional instance of the Timer Library that can be used as a template +# for the implementation of a functional timer library instance. This library instance can +# also be used to test build DXE, Runtime, DXE SAL, and DXE SMM modules that require timer +# services as well as EBC modules that require timer services. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseTimerLibNullTemplate + MODULE_UNI_FILE = BaseTimerLibNullTemplate.uni + FILE_GUID = f4731d79-537e-4505-bd52-c03f9b1f6b89 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + TimerLibNull.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni new file mode 100644 index 000000000..737d21aa0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni @@ -0,0 +1,19 @@ +// /** @file +// NULL instance of Timer Library as a template. +// +// A non-functional instance of the Timer Library that can be used as a template +// for the implementation of a functional timer library instance. This library instance can +// also be used to test build DXE, Runtime, DXE SAL, and DXE SMM modules that require timer +// services as well as EBC modules that require timer services. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "NULL instance of Timer Library as a template" + +#string STR_MODULE_DESCRIPTION #language en-US "A non-functional instance of the Timer Library that can be used as a template for the implementation of a functional timer library instance. This library instance can also be used to test build DXE, Runtime, DXE SAL, and DXE SMM modules that require timer services, as well as EBC modules that require timer services." + diff --git a/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c new file mode 100644 index 000000000..e095bb4d8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c @@ -0,0 +1,128 @@ +/** @file + A non-functional instance of the Timer Library. + + Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return The value of MicroSeconds inputted. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + ASSERT (FALSE); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return The value of NanoSeconds inputted. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + The counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + ASSERT (FALSE); + + return (UINT64)(-1); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + ASSERT (FALSE); + return 0; +} diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c new file mode 100644 index 000000000..28b4bf9d8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c @@ -0,0 +1,863 @@ +/** @file + UEFI Decompress Library implementation refer to UEFI specification. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseUefiDecompressLibInternals.h" + +/** + 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 + ) +{ + // + // Left shift NumOfBits of bits in advance + // + Sd->mBitBuf = (UINT32) LShiftU64 (((UINT64)Sd->mBitBuf), NumOfBits); + + // + // Copy data needed in bytes into mSbuBitBuf + // + while (NumOfBits > Sd->mBitCount) { + NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount); + Sd->mBitBuf |= (UINT32) LShiftU64 (((UINT64)Sd->mSubBitBuf), NumOfBits); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + 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 The 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; + UINT16 MaxTableLength; + + // + // 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++) { + if (BitLen[Index] > 16) { + return (UINT16) BAD_TABLE; + } + 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)); + MaxTableLength = (UINT16) (1U << 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) { + + if (Start[Len] >= NextCode || NextCode > MaxTableLength){ + return (UINT16) BAD_TABLE; + } + + 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 Position Set Length Array, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn The number of symbols. + @param nbit The 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); + + SetMem16 (&Sd->mPTTable[0] , sizeof (Sd->mPTTable), 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); + SetMem16 (&Sd->mCTable[0], sizeof (Sd->mCTable), 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 Array, + // 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 Array, + // Generate the Huffman code mapping table for Char&Len Set. + // + ReadCLen (Sd); + + // + // Read in the Position Set Code Length Array, + // 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) { + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done; + } + if (DataIdx >= Sd->mOrigSize) { + Sd->mBadTableFlag = (UINT16) BAD_TABLE; + goto Done; + } + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + + BytesRemain--; + } + // + // Once mOutBuf is fully filled, directly return + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done; + } + } + } + +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) || (CompressedSize + 8) < 8) { + return RETURN_INVALID_PARAMETER; + } + + *ScratchSize = sizeof (SCRATCH_DATA); + *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1); + + return RETURN_SUCCESS; +} + +/** + Decompresses a 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(). + If the Version is not 1 or 2, 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 +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); + ASSERT (Version == 1 || Version == 2); + + 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); +} diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf new file mode 100644 index 000000000..356c39a4f --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf @@ -0,0 +1,38 @@ +## @file +# UEFI Decompress Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseUefiDecompressLib + MODULE_UNI_FILE = BaseUefiDecompressLib.uni + FILE_GUID = 9ae5147d-b240-467f-a484-b024fdc42ee0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiDecompressLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BaseUefiDecompressLibInternals.h + BaseUefiDecompressLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni new file mode 100644 index 000000000..25f379d04 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni @@ -0,0 +1,16 @@ +// /** @file +// UEFI Decompress Library implementation. +// +// UEFI Decompress Library implementation. +// +// Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI Decompress Library and Tiano Custom Decompress Library implementation." + +#string STR_MODULE_DESCRIPTION #language en-US "Tiano custom decompression algorithm shares most of the code with the UEFI Decompress algorithm." + diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h new file mode 100644 index 000000000..4df3fa388 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h @@ -0,0 +1,248 @@ +/** @file + Internal data structure defintions for Base UEFI Decompress Library. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_UEFI_DECOMPRESS_LIB_INTERNALS_H__ +#define __BASE_UEFI_DECOMPRESS_LIB_INTERNALS_H__ + +#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; // The starting address of compressed data + UINT8 *mDstBase; // The 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. + If TableBits > 16, then ASSERT (). + + @param Sd The global scratch data. + @param NumOfChar The 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 Position Set Length Array, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn The number of symbols. + @param nbit The 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 + ); + +/** + Decompresses a 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. + @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 +UefiTianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ); +#endif diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.c b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.c new file mode 100644 index 000000000..5a73933d2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.c @@ -0,0 +1,213 @@ +/** @file + UEFI Decompress Library implementation refer to UEFI specification. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include "BaseUefiDecompressLibInternals.h" + +/** + 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 ( + VOID +) +{ + return ExtractGuidedSectionRegisterHandlers ( + &gTianoCustomDecompressGuid, + TianoDecompressGetInfo, + TianoDecompress + ); +} diff --git a/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf new file mode 100644 index 000000000..280a5f307 --- /dev/null +++ b/roms/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf @@ -0,0 +1,42 @@ +## @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 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseUefiTianoCustomDecompressLib + MODULE_UNI_FILE = BaseUefiDecompressLib.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 EBC +# + +[Sources] + BaseUefiDecompressLibInternals.h + BaseUefiDecompressLib.c + BaseUefiTianoCustomDecompressLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + ExtractGuidedSectionLib + +[Guids] + gTianoCustomDecompressGuid ## PRODUCES ## UNDEFINED # specifies tiano custom decompress algorithm. diff --git a/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c new file mode 100644 index 000000000..3dda3520a --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c @@ -0,0 +1,73 @@ +/** @file + Entry point to the DXE Core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include +#include + +// +// Cache copy of HobList pointer. +// +VOID *gHobList = NULL; + +/** + The entry point of PE/COFF Image for the DXE Core. + + This function is the entry point for the DXE Core. This function is required to call + ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return. + The DXE Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI + System Table and the image handle for the DXE Core itself have been established. + If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system. + + @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *HobStart + ) +{ + // + // Cache a pointer to the HobList + // + gHobList = HobStart; + + // + // Call the DXE Core entry point + // + ProcessModuleEntryPointList (HobStart); + + // + // Should never return + // + ASSERT(FALSE); + CpuDeadLoop (); +} + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + This function is required to call _ModuleEntryPoint() passing in HobStart. + + @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +EfiMain ( + IN VOID *HobStart + ) +{ + _ModuleEntryPoint (HobStart); +} diff --git a/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf new file mode 100644 index 000000000..72fd7572b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf @@ -0,0 +1,36 @@ +## @file +# Module entry point library for DXE core. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeCoreEntryPoint + MODULE_UNI_FILE = DxeCoreEntryPoint.uni + FILE_GUID = d258d6af-2fc0-4019-9c1f-1101c3dd19b5 + MODULE_TYPE = DXE_CORE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DxeCoreEntryPoint|DXE_CORE + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + DxeCoreEntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + DebugLib + diff --git a/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni new file mode 100644 index 000000000..af26f0bec --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni @@ -0,0 +1,16 @@ +// /** @file +// Module entry point library for DXE core. +// +// Module entry point library for DXE core. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for DXE core" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for DXE core." + diff --git a/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf b/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf new file mode 100644 index 000000000..3b277363c --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf @@ -0,0 +1,39 @@ +## @file +# Instance of HOB Library for DXE Core. +# +# HOB Library implementation for the DXE Core. Does not have a constructor. +# Uses gHobList defined in the DXE Core Entry Point Library. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeCoreHobLib + MODULE_UNI_FILE = DxeCoreHobLib.uni + FILE_GUID = 882ee1a3-35b2-412c-b8a2-7a8d34a7c390 + MODULE_TYPE = DXE_CORE + VERSION_STRING = 1.0 + LIBRARY_CLASS = HobLib|DXE_CORE + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + HobLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + DebugLib + DxeCoreEntryPoint + diff --git a/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni b/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni new file mode 100644 index 000000000..62249bb9b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of HOB Library for DXE Core. +// +// HOB Library implementation for the DXE Core. Does not have a constructor. +// Uses gHobList defined in the DXE Core Entry Point Library. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of HOB Library for DXE Core" + +#string STR_MODULE_DESCRIPTION #language en-US "HOB Library implementation for the DXE Core. Does not have a constructor. Uses gHobList defined in the DXE Core Entry Point Library." + diff --git a/roms/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c b/roms/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c new file mode 100644 index 000000000..9759e86b0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c @@ -0,0 +1,597 @@ +/** @file + HOB Library implementation for DxeCore driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer + to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through + the EFI System Table by looking up theHOB list GUID in the System Configuration Table. + Since the System Configuration Table does not exist that the time the DXE Core is + launched, the DXE Core uses a global variable from the DXE Core Entry Point Library + to manage the pointer to the HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + ASSERT (gHobList != NULL); + return gHobList; +} + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + Returns the next instance of the matched GUID HOB from the starting HOB. + + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION, and its GUID Name equals to the input Guid. + If such a HOB from the starting HOB pointer does not exist, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + Returns the first instance of the matched GUID HOB among the whole HOB list. + + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If such a HOB from the starting HOB pointer does not exist, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + + If the pointer to the HOB list is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + Get the system boot mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param VOID + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootModeHob ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList (); + + return HandOffHob->BootMode; +} + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory with Owner GUID. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + @param OwnerGUID GUID for the owner of this resource. + +**/ +VOID +EFIAPI +BuildResourceDescriptorWithOwnerHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_GUID *OwnerGUID + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a customized HOB tagged with a GUID for identification and returns + the start address of GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase. + For DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB + data field, and returns the start address of the GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification and copies the input + data to the HOB data field and returns the start address of the GUID HOB data. It can only be + invoked during PEI phase; for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase. + For DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + ASSERT (FALSE); +} + +/** + Builds a EFI_HOB_TYPE_FV3 HOB. + + This function builds a EFI_HOB_TYPE_FV3 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param AuthenticationStatus The authentication status. + @param ExtractedFv TRUE if the FV was extracted as a file within + another firmware volume. FALSE otherwise. + @param FvName The name of the Firmware Volume. + Valid only if IsExtractedFv is TRUE. + @param FileName The name of the file. + Valid only if IsExtractedFv is TRUE. + +**/ +VOID +EFIAPI +BuildFv3Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT32 AuthenticationStatus, + IN BOOLEAN ExtractedFv, + IN CONST EFI_GUID *FvName, OPTIONAL + IN CONST EFI_GUID *FileName OPTIONAL + ) +{ + ASSERT (FALSE); +} + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If the platform does not support Capsule Volume HOBs, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() because PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c new file mode 100644 index 000000000..ef730ec55 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c @@ -0,0 +1,449 @@ +/** @file + Provide generic extract guided section functions for Dxe phase. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +#define EXTRACT_HANDLER_TABLE_SIZE 0x10 + +UINT32 mNumberOfExtractHandler = 0; +UINT32 mMaxNumberOfExtractHandler = 0; + +GUID *mExtractHandlerGuidTable = NULL; +EXTRACT_GUIDED_SECTION_DECODE_HANDLER *mExtractDecodeHandlerTable = NULL; +EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *mExtractGetInfoHandlerTable = NULL; + +/** + Reallocates more global memory to store the registered guid and Handler list. + + @retval RETURN_SUCCESS Reallocated more global memory space to store guid and function tables. + @retval RETURN_OUT_OF_RESOURCES Not enough memory to allocate. +**/ +RETURN_STATUS +EFIAPI +ReallocateExtractHandlerTable ( + VOID + ) +{ + // + // Reallocate memory for GuidTable + // + mExtractHandlerGuidTable = ReallocatePool ( + mMaxNumberOfExtractHandler * sizeof (GUID), + (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (GUID), + mExtractHandlerGuidTable + ); + + if (mExtractHandlerGuidTable == NULL) { + goto Done; + } + + // + // Reallocate memory for Decode handler Table + // + mExtractDecodeHandlerTable = ReallocatePool ( + mMaxNumberOfExtractHandler * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER), + (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER), + mExtractDecodeHandlerTable + ); + + if (mExtractDecodeHandlerTable == NULL) { + goto Done; + } + + // + // Reallocate memory for GetInfo handler Table + // + mExtractGetInfoHandlerTable = ReallocatePool ( + mMaxNumberOfExtractHandler * sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER), + (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER), + mExtractGetInfoHandlerTable + ); + + if (mExtractGetInfoHandlerTable == NULL) { + goto Done; + } + + // + // Increase max handler number + // + mMaxNumberOfExtractHandler = mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE; + return RETURN_SUCCESS; + +Done: + if (mExtractHandlerGuidTable != NULL) { + FreePool (mExtractHandlerGuidTable); + } + if (mExtractDecodeHandlerTable != NULL) { + FreePool (mExtractDecodeHandlerTable); + } + if (mExtractGetInfoHandlerTable != NULL) { + FreePool (mExtractGetInfoHandlerTable); + } + + return RETURN_OUT_OF_RESOURCES; +} +/** + Constructor allocates the global memory to store the registered guid and Handler list. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval RETURN_SUCCESS Allocated the global memory space to store guid and function tables. + @retval RETURN_OUT_OF_RESOURCES Not enough memory to allocate. +**/ +RETURN_STATUS +EFIAPI +DxeExtractGuidedSectionLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return ReallocateExtractHandlerTable (); +} + +/** + Retrieve the list GUIDs that have been registered through ExtractGuidedSectionRegisterHandlers(). + + Sets ExtractHandlerGuidTable so it points at a callee allocated array of registered GUIDs. + The total number of GUIDs in the array are returned. Since the array of GUIDs is callee allocated + and caller must treat this array of GUIDs as read-only data. + If ExtractHandlerGuidTable is NULL, then ASSERT(). + + @param[out] ExtractHandlerGuidTable A pointer to the array of GUIDs that have been registered through + ExtractGuidedSectionRegisterHandlers(). + + @return The number of the supported extract guided Handler. + +**/ +UINTN +EFIAPI +ExtractGuidedSectionGetGuidList ( + OUT GUID **ExtractHandlerGuidTable + ) +{ + ASSERT (ExtractHandlerGuidTable != NULL); + + *ExtractHandlerGuidTable = mExtractHandlerGuidTable; + return mNumberOfExtractHandler; +} + +/** + Registers handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and EXTRACT_GUIDED_SECTION_DECODE_HANDLER + for a specific GUID section type. + + Registers the handlers specified by GetInfoHandler and DecodeHandler with the GUID specified by SectionGuid. + If the GUID value specified by SectionGuid has already been registered, then return RETURN_ALREADY_STARTED. + If there are not enough resources available to register the handlers then RETURN_OUT_OF_RESOURCES is returned. + + If SectionGuid is NULL, then ASSERT(). + If GetInfoHandler is NULL, then ASSERT(). + If DecodeHandler is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the handlers + of the GUIDed section type being registered. + @param[in] GetInfoHandler The pointer to a function that 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. + @param[in] DecodeHandler The pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to register the handlers. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionRegisterHandlers ( + IN CONST GUID *SectionGuid, + IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler, + IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler + ) +{ + UINT32 Index; + VOID *GuidData; + + // + // Check input parameter. + // + ASSERT (SectionGuid != NULL); + ASSERT (GetInfoHandler != NULL); + ASSERT (DecodeHandler != NULL); + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < mNumberOfExtractHandler; Index ++) { + if (CompareGuid (&mExtractHandlerGuidTable[Index], SectionGuid)) { + // + // If the guided handler has been registered before, only update its handler. + // + mExtractDecodeHandlerTable [Index] = DecodeHandler; + mExtractGetInfoHandlerTable [Index] = GetInfoHandler; + return RETURN_SUCCESS; + } + } + + // + // Check the global table is enough to contain new Handler. + // + if (mNumberOfExtractHandler >= mMaxNumberOfExtractHandler) { + if (ReallocateExtractHandlerTable () != RETURN_SUCCESS) { + return RETURN_OUT_OF_RESOURCES; + } + } + + // + // Register new Handler and guid value. + // + CopyGuid (&mExtractHandlerGuidTable [mNumberOfExtractHandler], SectionGuid); + mExtractDecodeHandlerTable [mNumberOfExtractHandler] = DecodeHandler; + mExtractGetInfoHandlerTable [mNumberOfExtractHandler++] = GetInfoHandler; + + // + // Install the Guided Section GUID configuration table to record the GUID itself. + // Then the content of the configuration table buffer will be the same as the GUID value itself. + // + GuidData = AllocateCopyPool (sizeof (GUID), (VOID *) SectionGuid); + if (GuidData != NULL) { + gBS->InstallConfigurationTable ((EFI_GUID *) SectionGuid, GuidData); + } + + return RETURN_SUCCESS; +} + +/** + Retrieves a GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to retrieve and return 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 any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the associated handler + of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to retrieve the OutputBufferSize, ScratchSize, and Attributes values. The return status from the handler of + type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER is returned. + + 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 Successfully obtained the required information. + @retval RETURN_UNSUPPORTED The GUID from the section specified by InputSection does not match any of + the GUIDs registered with ExtractGuidedSectionRegisterHandlers(). + @retval Others The return status from the handler associated with the GUID retrieved from + the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + UINT32 Index; + EFI_GUID *SectionDefinitionGuid; + + ASSERT (InputSection != NULL); + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < mNumberOfExtractHandler; Index ++) { + if (CompareGuid (&mExtractHandlerGuidTable[Index], SectionDefinitionGuid)) { + // + // Call the match handler to getinfo for the input section data. + // + return mExtractGetInfoHandlerTable [Index] ( + InputSection, + OutputBufferSize, + ScratchBufferSize, + SectionAttribute + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves the GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to decode the data in a GUIDed section and return the result in a caller + allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the associated handler + of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to decode InputSection 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. This function is responsible for computing the EFI_AUTH_STATUS_PLATFORM_OVERRIDE + bit of in AuthenticationStatus. The return status from the handler of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER is returned. + + 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. + + @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 +ExtractGuidedSectionDecode ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + IN VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + UINT32 Index; + EFI_GUID *SectionDefinitionGuid; + + // + // Check the input parameters + // + ASSERT (InputSection != NULL); + ASSERT (OutputBuffer != NULL); + ASSERT (AuthenticationStatus != NULL); + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered extract handler for the input guided section. + // + for (Index = 0; Index < mNumberOfExtractHandler; Index ++) { + if (CompareGuid (&mExtractHandlerGuidTable[Index], SectionDefinitionGuid)) { + // + // Call the match handler to extract raw data for the input section data. + // + return mExtractDecodeHandlerTable [Index] ( + InputSection, + OutputBuffer, + ScratchBuffer, + AuthenticationStatus + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and + EXTRACT_GUIDED_SECTION_DECODE_HANDLER for a specific GUID section type. + + Retrieves the handlers associated with SectionGuid and returns them in + GetInfoHandler and DecodeHandler. + + If the GUID value specified by SectionGuid has not been registered, then + return RETURN_NOT_FOUND. + + If SectionGuid is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the handlers of the GUIDed + section type being retrieved. + @param[out] GetInfoHandler Pointer to a function that 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. + This is an optional parameter that may be NULL. If it is NULL, then + the previously registered handler is not returned. + @param[out] DecodeHandler Pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. This is an optional parameter that may be NULL. + If it is NULL, then the previously registered handler is not returned. + + @retval RETURN_SUCCESS The handlers were retrieved. + @retval RETURN_NOT_FOUND No handlers have been registered with the specified GUID. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetHandlers ( + IN CONST GUID *SectionGuid, + OUT EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *GetInfoHandler, OPTIONAL + OUT EXTRACT_GUIDED_SECTION_DECODE_HANDLER *DecodeHandler OPTIONAL + ) +{ + UINT32 Index; + + // + // Check input parameter. + // + ASSERT (SectionGuid != NULL); + + // + // Search the match registered GetInfo handler for the input guided section. + // + for (Index = 0; Index < mNumberOfExtractHandler; Index ++) { + if (CompareGuid (&mExtractHandlerGuidTable[Index], SectionGuid)) { + + // + // If the guided handler has been registered before, then return the registered handlers. + // + if (GetInfoHandler != NULL) { + *GetInfoHandler = mExtractGetInfoHandlerTable[Index]; + } + if (DecodeHandler != NULL) { + *DecodeHandler = mExtractDecodeHandlerTable[Index]; + } + return RETURN_SUCCESS; + } + } + return RETURN_NOT_FOUND; +} diff --git a/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf new file mode 100644 index 000000000..33eeab405 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf @@ -0,0 +1,42 @@ +## @file +# Instance of ExtractGuidedSection Library for DXE phase. +# +# This library provides generic extract guided section functions for DXE module. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeExtractGuidedSectionLib + MODULE_UNI_FILE = DxeExtractGuidedSectionLib.uni + FILE_GUID = f773469b-e265-4b0c-b0a6-2f971fbfe72b + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ExtractGuidedSectionLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = DxeExtractGuidedSectionLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeExtractGuidedSectionLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + diff --git a/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni new file mode 100644 index 000000000..563ccdea2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of ExtractGuidedSection Library for DXE phase. +// +// This library provides generic extract guided section functions for DXE module. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of ExtractGuidedSection Library for DXE phase" + +#string STR_MODULE_DESCRIPTION #language en-US "This library provides generic extract guided section functions for a DXE module." + diff --git a/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf b/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf new file mode 100644 index 000000000..603cf6388 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf @@ -0,0 +1,43 @@ +## @file +# Instance of HOB Library using HOB list from EFI Configuration Table. +# +# HOB Library implementation that retrieves the HOB List +# from the System Configuration Table in the EFI System Table. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeHobLib + MODULE_UNI_FILE = DxeHobLib.uni + FILE_GUID = f12b59c9-76d0-4661-ad7c-f04d1bef0558 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = HobLib|DXE_DRIVER DXE_RUNTIME_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = HobLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + HobLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + DebugLib + UefiLib + +[Guids] + gEfiHobListGuid ## CONSUMES ## SystemTable + diff --git a/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni b/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni new file mode 100644 index 000000000..dcc1cb40a --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of HOB Library using HOB list from EFI Configuration Table. +// +// HOB Library implementation that retrieves the HOB List +// from the System Configuration Table in the EFI System Table. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of HOB Library using HOB list from EFI Configuration Table" + +#string STR_MODULE_DESCRIPTION #language en-US "The HOB Library implementation that retrieves the HOB List from the System Configuration Table in the EFI System Table." + diff --git a/roms/edk2/MdePkg/Library/DxeHobLib/HobLib.c b/roms/edk2/MdePkg/Library/DxeHobLib/HobLib.c new file mode 100644 index 000000000..ffac638d1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHobLib/HobLib.c @@ -0,0 +1,631 @@ +/** @file + HOB Library implementation for Dxe Phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +VOID *mHobList = NULL; + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer + to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through + the EFI System Table by looking up theHOB list GUID in the System Configuration Table. + Since the System Configuration Table does not exist that the time the DXE Core is + launched, the DXE Core uses a global variable from the DXE Core Entry Point Library + to manage the pointer to the HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + This function also caches the pointer to the HOB list retrieved. + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + EFI_STATUS Status; + + if (mHobList == NULL) { + Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &mHobList); + ASSERT_EFI_ERROR (Status); + ASSERT (mHobList != NULL); + } + return mHobList; +} + +/** + The constructor function caches the pointer to HOB list by calling GetHobList() + and 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 gets HobList. + +**/ +EFI_STATUS +EFIAPI +HobLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + GetHobList (); + + return EFI_SUCCESS; +} + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + Returns the next instance of the matched GUID HOB from the starting HOB. + + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + Returns the first instance of the matched GUID HOB among the whole HOB list. + + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + + If the pointer to the HOB list is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + Get the system boot mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param VOID + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootModeHob ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList (); + + return HandOffHob->BootMode; +} + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory with Owner GUID. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + @param OwnerGUID GUID for the owner of this resource. + +**/ +VOID +EFIAPI +BuildResourceDescriptorWithOwnerHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_GUID *OwnerGUID + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a customized HOB tagged with a GUID for identification and returns + the start address of GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB + data field, and returns the start address of the GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification and copies the input + data to the HOB data field and returns the start address of the GUID HOB data. It can only be + invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + ASSERT (FALSE); +} + +/** + Builds a EFI_HOB_TYPE_FV3 HOB. + + This function builds a EFI_HOB_TYPE_FV3 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param AuthenticationStatus The authentication status. + @param ExtractedFv TRUE if the FV was extracted as a file within + another firmware volume. FALSE otherwise. + @param FvName The name of the Firmware Volume. + Valid only if IsExtractedFv is TRUE. + @param FileName The name of the file. + Valid only if IsExtractedFv is TRUE. + +**/ +VOID +EFIAPI +BuildFv3Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT32 AuthenticationStatus, + IN BOOLEAN ExtractedFv, + IN CONST EFI_GUID *FvName, OPTIONAL + IN CONST EFI_GUID *FileName OPTIONAL + ) +{ + ASSERT (FALSE); +} + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If the platform does not support Capsule Volume HOBs, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} diff --git a/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf b/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf new file mode 100644 index 000000000..c719481cd --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf @@ -0,0 +1,43 @@ +## @file +# DXE instance of Hsti Library. +# +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeHstiLib + MODULE_UNI_FILE = DxeHstiLib.uni + FILE_GUID = 7DE1C620-F587-4116-A36D-40F3467B9A0C + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = HstiLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + +[Sources] + HstiAip.c + HstiDxe.c + HstiDxe.h + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + +[Guids] +## SOMETIMES_PRODUCES ## GUID +## SOMETIMES_CONSUMES ## GUID + gAdapterInfoPlatformSecurityGuid + +[Protocols] +## SOMETIMES_PRODUCES +## SOMETIMES_CONSUMES + gEfiAdapterInformationProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni b/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni new file mode 100644 index 000000000..6c6b30592 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni @@ -0,0 +1,14 @@ +// /** @file +// DXE instance of Hsti Library. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "DXE instance of Hsti Library." + +#string STR_MODULE_DESCRIPTION #language en-US "The HSTI Library implementation that create, get, or update HSTI table in DXE phase." + diff --git a/roms/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c new file mode 100644 index 000000000..1a3dfc148 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c @@ -0,0 +1,169 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "HstiDxe.h" + +/** + Returns the current state information for the adapter. + + This function returns information of type InformationType from the adapter. + If an adapter does not support the requested informational type, then + EFI_UNSUPPORTED is returned. + + @param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance. + @param[in] InformationType A pointer to an EFI_GUID that defines the contents of InformationBlock. + @param[out] InformationBlock The service returns a pointer to the buffer with the InformationBlock + structure which contains details about the data specific to InformationType. + @param[out] InformationBlockSize The driver returns the size of the InformationBlock in bytes. + + @retval EFI_SUCCESS The InformationType information was retrieved. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER InformationBlock is NULL. + @retval EFI_INVALID_PARAMETER InformationBlockSize is NULL. + +**/ +EFI_STATUS +EFIAPI +HstiAipGetInfo ( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + IN EFI_GUID *InformationType, + OUT VOID **InformationBlock, + OUT UINTN *InformationBlockSize + ) +{ + HSTI_AIP_PRIVATE_DATA *HstiAip; + + if ((This == NULL) || (InformationBlock == NULL) || (InformationBlockSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (InformationType, &gAdapterInfoPlatformSecurityGuid)) { + return EFI_UNSUPPORTED; + } + + HstiAip = HSTI_AIP_PRIVATE_DATA_FROM_THIS(This); + + *InformationBlock = AllocateCopyPool (HstiAip->HstiSize, HstiAip->Hsti); + if (*InformationBlock == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *InformationBlockSize = HstiAip->HstiSize; + return EFI_SUCCESS; +} + +/** + Sets state information for an adapter. + + This function sends information of type InformationType for an adapter. + If an adapter does not support the requested information type, then EFI_UNSUPPORTED + is returned. + + @param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance. + @param[in] InformationType A pointer to an EFI_GUID that defines the contents of InformationBlock. + @param[in] InformationBlock A pointer to the InformationBlock structure which contains details + about the data specific to InformationType. + @param[in] InformationBlockSize The size of the InformationBlock in bytes. + + @retval EFI_SUCCESS The information was received and interpreted successfully. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER InformationBlock is NULL. + @retval EFI_WRITE_PROTECTED The InformationType cannot be modified using EFI_ADAPTER_INFO_SET_INFO(). + +**/ +EFI_STATUS +EFIAPI +HstiAipSetInfo ( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN VOID *InformationBlock, + IN UINTN InformationBlockSize + ) +{ + HSTI_AIP_PRIVATE_DATA *HstiAip; + VOID *NewHsti; + + if ((This == NULL) || (InformationBlock == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (InformationType, &gAdapterInfoPlatformSecurityGuid)) { + return EFI_UNSUPPORTED; + } + + if (!InternalHstiIsValidTable (InformationBlock, InformationBlockSize)) { + return EFI_VOLUME_CORRUPTED; + } + + HstiAip = HSTI_AIP_PRIVATE_DATA_FROM_THIS(This); + + if (InformationBlockSize > HstiAip->HstiMaxSize) { + NewHsti = AllocateZeroPool (InformationBlockSize); + if (NewHsti == NULL) { + return EFI_OUT_OF_RESOURCES; + } + FreePool (HstiAip->Hsti); + HstiAip->Hsti = NewHsti; + HstiAip->HstiSize = 0; + HstiAip->HstiMaxSize = InformationBlockSize; + } + + CopyMem (HstiAip->Hsti, InformationBlock, InformationBlockSize); + HstiAip->HstiSize = InformationBlockSize; + return EFI_SUCCESS; +} + +/** + Get a list of supported information types for this instance of the protocol. + + This function returns a list of InformationType GUIDs that are supported on an + adapter with this instance of EFI_ADAPTER_INFORMATION_PROTOCOL. The list is returned + in InfoTypesBuffer, and the number of GUID pointers in InfoTypesBuffer is returned in + InfoTypesBufferCount. + + @param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance. + @param[out] InfoTypesBuffer A pointer to the array of InformationType GUIDs that are supported + by This. + @param[out] InfoTypesBufferCount A pointer to the number of GUIDs present in InfoTypesBuffer. + + @retval EFI_SUCCESS The list of information type GUIDs that are supported on this adapter was + returned in InfoTypesBuffer. The number of information type GUIDs was + returned in InfoTypesBufferCount. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER InfoTypesBuffer is NULL. + @retval EFI_INVALID_PARAMETER InfoTypesBufferCount is NULL. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. + +**/ +EFI_STATUS +EFIAPI +HstiAipGetSupportedTypes ( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + OUT EFI_GUID **InfoTypesBuffer, + OUT UINTN *InfoTypesBufferCount + ) +{ + if ((This == NULL) || (InfoTypesBuffer == NULL) || (InfoTypesBufferCount == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *InfoTypesBuffer = AllocateCopyPool (sizeof(gAdapterInfoPlatformSecurityGuid), &gAdapterInfoPlatformSecurityGuid); + if (*InfoTypesBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *InfoTypesBufferCount = 1; + + return EFI_SUCCESS; +} + +EFI_ADAPTER_INFORMATION_PROTOCOL mAdapterInformationProtocol = { + HstiAipGetInfo, + HstiAipSetInfo, + HstiAipGetSupportedTypes, +}; diff --git a/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c new file mode 100644 index 000000000..4e1c67616 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c @@ -0,0 +1,606 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "HstiDxe.h" + +/** + Find HSTI table in AIP protocol, and return the data. + This API will return the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param HstiData HSTI data. This buffer is allocated by callee, and it + is the responsibility of the caller to free it after + using it. + @param HstiSize HSTI size + + @return Aip The AIP protocol having this HSTI. + @return NULL There is not HSTI table with the Role and ImplementationID published in system. +**/ +VOID * +InternalHstiFindAip ( + IN UINT32 Role, + IN CHAR16 *ImplementationID OPTIONAL, + OUT VOID **HstiData OPTIONAL, + OUT UINTN *HstiSize OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN Index; + EFI_GUID *InfoTypesBuffer; + UINTN InfoTypesBufferCount; + UINTN InfoTypesIndex; + EFI_ADAPTER_INFORMATION_PROTOCOL *AipCandidate; + VOID *InformationBlock; + UINTN InformationBlockSize; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiAdapterInformationProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + Hsti = NULL; + Aip = NULL; + InformationBlock = NULL; + InformationBlockSize = 0; + for (Index = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiAdapterInformationProtocolGuid, + (VOID **)&Aip + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Check AIP + // + Status = Aip->GetSupportedTypes ( + Aip, + &InfoTypesBuffer, + &InfoTypesBufferCount + ); + if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL) || (InfoTypesBufferCount == 0)) { + continue; + } + + AipCandidate = NULL; + for (InfoTypesIndex = 0; InfoTypesIndex < InfoTypesBufferCount; InfoTypesIndex++) { + if (CompareGuid (&InfoTypesBuffer[InfoTypesIndex], &gAdapterInfoPlatformSecurityGuid)) { + AipCandidate = Aip; + break; + } + } + FreePool (InfoTypesBuffer); + + if (AipCandidate == NULL) { + continue; + } + + // + // Check HSTI Role + // + Aip = AipCandidate; + Status = Aip->GetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + &InformationBlock, + &InformationBlockSize + ); + if (EFI_ERROR (Status)) { + continue; + } + + Hsti = InformationBlock; + if ((Hsti->Role == Role) && + ((ImplementationID == NULL) || (StrCmp (ImplementationID, Hsti->ImplementationID) == 0))) { + break; + } else { + Hsti = NULL; + FreePool (InformationBlock); + continue; + } + } + FreePool (Handles); + + if (Hsti == NULL) { + return NULL; + } + + if (HstiData != NULL) { + *HstiData = InformationBlock; + } + if (HstiSize != NULL) { + *HstiSize = InformationBlockSize; + } + return Aip; +} + +/** + Return if input HSTI data follows HSTI specification. + + @param HstiData HSTI data + @param HstiSize HSTI size + + @retval TRUE HSTI data follows HSTI specification. + @retval FALSE HSTI data does not follow HSTI specification. +**/ +BOOLEAN +InternalHstiIsValidTable ( + IN VOID *HstiData, + IN UINTN HstiSize + ) +{ + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN Index; + CHAR16 *ErrorString; + CHAR16 ErrorChar; + UINTN ErrorStringSize; + UINTN ErrorStringLength; + + Hsti = HstiData; + + // + // basic check for header + // + if (HstiData == NULL) { + DEBUG ((EFI_D_ERROR, "HstiData == NULL\n")); + return FALSE; + } + if (HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) { + DEBUG ((EFI_D_ERROR, "HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)\n")); + return FALSE; + } + if (((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < Hsti->SecurityFeaturesSize) { + DEBUG ((EFI_D_ERROR, "((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < SecurityFeaturesSize\n")); + return FALSE; + } + + // + // Check Version + // + if (Hsti->Version != PLATFORM_SECURITY_VERSION_VNEXTCS) { + DEBUG ((EFI_D_ERROR, "Version != PLATFORM_SECURITY_VERSION_VNEXTCS\n")); + return FALSE; + } + + // + // Check Role + // + if ((Hsti->Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) || + (Hsti->Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM)) { + DEBUG ((EFI_D_ERROR, "Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE ||\n")); + DEBUG ((EFI_D_ERROR, "Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM\n")); + return FALSE; + } + + // + // Check ImplementationID + // + for (Index = 0; Index < sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0]); Index++) { + if (Hsti->ImplementationID[Index] == 0) { + break; + } + } + if (Index == sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0])) { + DEBUG ((EFI_D_ERROR, "ImplementationID has no NUL CHAR\n")); + return FALSE; + } + + ErrorStringSize = HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY) - Hsti->SecurityFeaturesSize * 3; + ErrorString = (CHAR16 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3); + + // + // basic check for ErrorString + // + if (ErrorStringSize == 0) { + DEBUG ((EFI_D_ERROR, "ErrorStringSize == 0\n")); + return FALSE; + } + if ((ErrorStringSize & BIT0) != 0) { + DEBUG ((EFI_D_ERROR, "(ErrorStringSize & BIT0) != 0\n")); + return FALSE; + } + + // + // ErrorString might not be CHAR16 aligned. + // + CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); + for (ErrorStringLength = 0; (ErrorChar != 0) && (ErrorStringLength < (ErrorStringSize/2)); ErrorStringLength++) { + ErrorString++; + CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); + } + + // + // check the length of ErrorString + // + if (ErrorChar != 0) { + DEBUG ((EFI_D_ERROR, "ErrorString has no NUL CHAR\n")); + return FALSE; + } + if (ErrorStringLength == (ErrorStringSize/2)) { + DEBUG ((EFI_D_ERROR, "ErrorString Length incorrect\n")); + return FALSE; + } + + return TRUE; +} + +/** + Publish HSTI table in AIP protocol. + + One system should have only one PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE. + + If the Role is NOT PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE, + SecurityFeaturesRequired field will be ignored. + + @param Hsti HSTI data + @param HstiSize HSTI size + + @retval EFI_SUCCESS The HSTI data is published in AIP protocol. + @retval EFI_ALREADY_STARTED There is already HSTI table with Role and ImplementationID published in system. + @retval EFI_VOLUME_CORRUPTED The input HSTI data does not follow HSTI specification. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to publish HSTI data in AIP protocol. +**/ +EFI_STATUS +EFIAPI +HstiLibSetTable ( + IN VOID *Hsti, + IN UINTN HstiSize + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + HSTI_AIP_PRIVATE_DATA *HstiAip; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + UINT32 Role; + CHAR16 *ImplementationID; + UINT32 SecurityFeaturesSize; + UINT8 *SecurityFeaturesRequired; + + if (!InternalHstiIsValidTable (Hsti, HstiSize)) { + return EFI_VOLUME_CORRUPTED; + } + + Role = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->Role; + ImplementationID = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->ImplementationID; + Aip = InternalHstiFindAip (Role, ImplementationID, NULL, NULL); + if (Aip != NULL) { + return EFI_ALREADY_STARTED; + } + + HstiAip = AllocateZeroPool (sizeof(HSTI_AIP_PRIVATE_DATA)); + if (HstiAip == NULL) { + return EFI_OUT_OF_RESOURCES; + } + HstiAip->Hsti = AllocateCopyPool (HstiSize, Hsti); + if (HstiAip->Hsti == NULL) { + FreePool (HstiAip); + return EFI_OUT_OF_RESOURCES; + } + if (Role != PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) { + SecurityFeaturesRequired = (UINT8 *)HstiAip->Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY); + SecurityFeaturesSize = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->SecurityFeaturesSize; + ZeroMem (SecurityFeaturesRequired, SecurityFeaturesSize); + } + + HstiAip->Signature = HSTI_AIP_PRIVATE_SIGNATURE; + CopyMem (&HstiAip->Aip, &mAdapterInformationProtocol, sizeof(EFI_ADAPTER_INFORMATION_PROTOCOL)); + HstiAip->HstiSize = HstiSize; + HstiAip->HstiMaxSize = HstiSize; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiAdapterInformationProtocolGuid, + &HstiAip->Aip, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (HstiAip->Hsti); + FreePool (HstiAip); + } + + return Status; +} + +/** + Search HSTI table in AIP protocol, and return the data. + This API will return the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param Hsti HSTI data. This buffer is allocated by callee, and it + is the responsibility of the caller to free it after + using it. + @param HstiSize HSTI size + + @retval EFI_SUCCESS The HSTI data in AIP protocol is returned. + @retval EFI_NOT_FOUND There is not HSTI table with the Role and ImplementationID published in system. +**/ +EFI_STATUS +EFIAPI +HstiLibGetTable ( + IN UINT32 Role, + IN CHAR16 *ImplementationID OPTIONAL, + OUT VOID **Hsti, + OUT UINTN *HstiSize + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + + Aip = InternalHstiFindAip (Role, ImplementationID, Hsti, HstiSize); + if (Aip == NULL) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +/** + Record FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + @param Set TRUE means to set the FeaturesVerified bit. + FALSE means to clear the FeaturesVerified bit. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +InternalHstiRecordFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 Bit, + IN BOOLEAN Set + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN HstiSize; + UINT8 *SecurityFeaturesVerified; + EFI_STATUS Status; + + Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize); + if (Aip == NULL) { + return EFI_NOT_STARTED; + } + + if (ByteIndex >= Hsti->SecurityFeaturesSize) { + return EFI_UNSUPPORTED; + } + + SecurityFeaturesVerified = (UINT8 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 2); + + if (Set) { + SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] | (Bit)); + } else { + SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] & (~Bit)); + } + + Status = Aip->SetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + Hsti, + HstiSize + ); + FreePool (Hsti); + return Status; +} + +/** + Set FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +EFIAPI +HstiLibSetFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 BitMask + ) +{ + return InternalHstiRecordFeaturesVerified ( + Role, + ImplementationID, + ByteIndex, + BitMask, + TRUE + ); +} + +/** + Clear FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +EFIAPI +HstiLibClearFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 BitMask + ) +{ + return InternalHstiRecordFeaturesVerified ( + Role, + ImplementationID, + ByteIndex, + BitMask, + FALSE + ); +} + +/** + Record ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + @param Append TRUE means to append the ErrorString to HSTI table. + FALSE means to set the ErrorString in HSTI table. + + @retval EFI_SUCCESS The ErrorString of HSTI data is published in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +InternalHstiRecordErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString, + IN BOOLEAN Append + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN HstiSize; + UINTN StringSize; + VOID *NewHsti; + UINTN NewHstiSize; + UINTN Offset; + EFI_STATUS Status; + + Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize); + if (Aip == NULL) { + return EFI_NOT_STARTED; + } + + if (Append) { + Offset = HstiSize - sizeof(CHAR16); + } else { + Offset = sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3; + } + StringSize = StrSize (ErrorString); + + NewHstiSize = Offset + StringSize; + NewHsti = AllocatePool (NewHstiSize); + if (NewHsti == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (NewHsti, Hsti, Offset); + CopyMem ((UINT8 *)NewHsti + Offset, ErrorString, StringSize); + + Status = Aip->SetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + NewHsti, + NewHstiSize + ); + FreePool (Hsti); + FreePool (NewHsti); + return Status; +} + +/** + Append ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + + @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +EFIAPI +HstiLibAppendErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString + ) +{ + return InternalHstiRecordErrorString ( + Role, + ImplementationID, + ErrorString, + TRUE + ); +} + +/** + Set a new ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + + @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +EFIAPI +HstiLibSetErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString + ) +{ + return InternalHstiRecordErrorString ( + Role, + ImplementationID, + ErrorString, + FALSE + ); +} diff --git a/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h new file mode 100644 index 000000000..218297a3b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h @@ -0,0 +1,59 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _HSTI_DXE_H_ +#define _HSTI_DXE_H_ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define HSTI_AIP_PRIVATE_SIGNATURE SIGNATURE_32('H', 'S', 'T', 'I') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_ADAPTER_INFORMATION_PROTOCOL Aip; + VOID *Hsti; + UINTN HstiSize; + UINTN HstiMaxSize; +} HSTI_AIP_PRIVATE_DATA; + +#define HSTI_AIP_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + HSTI_AIP_PRIVATE_DATA, \ + Aip, \ + HSTI_AIP_PRIVATE_SIGNATURE \ + ) + +#define HSTI_DEFAULT_ERROR_STRING_LEN 255 + +extern EFI_ADAPTER_INFORMATION_PROTOCOL mAdapterInformationProtocol; + +/** + Return if input HSTI data follows HSTI specification. + + @param HstiData HSTI data + @param HstiSize HSTI size + + @retval TRUE HSTI data follows HSTI specification. + @retval FALSE HSTI data does not follow HSTI specification. +**/ +BOOLEAN +InternalHstiIsValidTable ( + IN VOID *HstiData, + IN UINTN HstiSize + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h new file mode 100644 index 000000000..b6797c358 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h @@ -0,0 +1,166 @@ +/** @file + Internal include file of DXE CPU IO2 Library. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DXE_CPUIO2_LIB_INTERNAL_H_ +#define _DXE_CPUIO2_LIB_INTERNAL_H_ + +#include + +#include + +#include +#include +#include +#include + + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The read value is returned. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI CPU I/O space. + +**/ +UINT64 +EFIAPI +IoReadWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ); + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width and value specified by Width + and Data respectively. Data is returned. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return The parameter of Data. + +**/ +UINT64 +EFIAPI +IoWriteWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ); + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The port is read Count times, and the read data is stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifoWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width specified by Width. + The port is written Count times, and the write data is retrieved from the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to write I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoWriteFifoWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads memory-mapped registers in the EFI system memory space. + + Reads the MMIO registers specified by Address with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioReadWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ); + +/** + Writes memory-mapped registers in the EFI system memory space. + + Writes the MMIO registers specified by Address with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioWriteWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf new file mode 100644 index 000000000..16cec7e67 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf @@ -0,0 +1,47 @@ +## @file +# I/O Library instance based on EFI_CPU_IO2_PROTOCOL. +# +# I/O Library implementation that uses the CPU I/O2 Protocol for I/O and MMIO operations. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeIoLibCpuIo2 + MODULE_UNI_FILE = DxeIoLibCpuIo2.uni + FILE_GUID = 33D33BF3-349E-4768-9459-836A9F7558FB + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib|DXE_DRIVER + CONSTRUCTOR = IoLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + IoLibMmioBuffer.c + DxeCpuIo2LibInternal.h + IoHighLevel.c + IoLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiBootServicesTableLib + +[Protocols] + gEfiCpuIo2ProtocolGuid ## CONSUMES + +[Depex] + gEfiCpuIo2ProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni new file mode 100644 index 000000000..1b3caa8b9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni @@ -0,0 +1,16 @@ +// /** @file +// I/O Library instance based on EFI_CPU_IO2_PROTOCOL. +// +// I/O Library implementation that uses the CPU I/O2 Protocol for I/O and MMIO operations. +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "I/O Library instance based on EFI_CPU_IO2_PROTOCOL" + +#string STR_MODULE_DESCRIPTION #language en-US "I/O Library implementation that uses the CPU I/O2 Protocol for I/O and MMIO operations." + diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c new file mode 100644 index 000000000..ac4d3a684 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c @@ -0,0 +1,2301 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "DxeCpuIo2LibInternal.h" + +/** + Reads an 8-bit I/O port, performs a bitwise OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) | OrData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) & AndData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) ((IoRead8 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) | OrData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) & AndData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) ((IoRead16 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) | OrData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) & AndData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) ((MmioRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) | OrData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) & AndData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) ((MmioRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c new file mode 100644 index 000000000..21f88d985 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c @@ -0,0 +1,863 @@ +/** @file + I/O Library instance based on EFI_CPU_IO2_PROTOCOL. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeCpuIo2LibInternal.h" + +// +// Global variable to cache pointer to CpuIo2 protocol. +// +EFI_CPU_IO2_PROTOCOL *mCpuIo = NULL; + +/** + The constructor function caches the pointer to CpuIo2 protocol. + + The constructor function locates CpuIo2 protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +IoLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The read value is returned. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI CPU I/O space. + +**/ +UINT64 +EFIAPI +IoReadWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ) +{ + EFI_STATUS Status; + UINT64 Data; + + Status = mCpuIo->Io.Read (mCpuIo, Width, Port, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width and value specified by Width + and Data respectively. Data is returned. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return The parameter of Data. + +**/ +UINT64 +EFIAPI +IoWriteWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ) +{ + EFI_STATUS Status; + + Status = mCpuIo->Io.Write (mCpuIo, Width, Port, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The port is read Count times, and the read data is stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifoWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = mCpuIo->Io.Read (mCpuIo, Width, Port, Count, Buffer); + ASSERT_EFI_ERROR (Status); +} + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width specified by Width. + The port is written Count times, and the write data is retrieved from the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to write I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoWriteFifoWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = mCpuIo->Io.Write (mCpuIo, Width, Port, Count, Buffer); + ASSERT_EFI_ERROR (Status); +} + +/** + Reads memory-mapped registers in the EFI system memory space. + + Reads the MMIO registers specified by Address with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioReadWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ) +{ + EFI_STATUS Status; + UINT64 Data; + + Status = mCpuIo->Mem.Read (mCpuIo, Width, Address, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Writes memory-mapped registers in the EFI system memory space. + + Writes the MMIO registers specified by Address with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioWriteWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ) +{ + EFI_STATUS Status; + + Status = mCpuIo->Mem.Write (mCpuIo, Width, Address, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + return (UINT8)IoReadWorker (Port, EfiCpuIoWidthUint8); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + return (UINT8)IoWriteWorker (Port, EfiCpuIoWidthUint8, Value); +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + return (UINT16)IoReadWorker (Port, EfiCpuIoWidthUint16); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + return (UINT16)IoWriteWorker (Port, EfiCpuIoWidthUint16, Value); +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + return (UINT32)IoReadWorker (Port, EfiCpuIoWidthUint32); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + return (UINT32)IoWriteWorker (Port, EfiCpuIoWidthUint32, Value); +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + return IoReadWorker (Port, EfiCpuIoWidthUint64); +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + return IoWriteWorker (Port, EfiCpuIoWidthUint64, Value); +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + IoReadFifoWorker (Port, EfiCpuIoWidthFifoUint8, Count, Buffer); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + IoWriteFifoWorker (Port, EfiCpuIoWidthFifoUint8, Count, Buffer); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + IoReadFifoWorker (Port, EfiCpuIoWidthFifoUint16, Count, Buffer); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + IoWriteFifoWorker (Port, EfiCpuIoWidthFifoUint16, Count, Buffer); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + IoReadFifoWorker (Port, EfiCpuIoWidthFifoUint32, Count, Buffer); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + IoWriteFifoWorker (Port, EfiCpuIoWidthFifoUint32, Count, Buffer); +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + return (UINT8)MmioReadWorker (Address, EfiCpuIoWidthUint8); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return (UINT8)MmioWriteWorker (Address, EfiCpuIoWidthUint8, Value); +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + return (UINT16)MmioReadWorker (Address, EfiCpuIoWidthUint16); +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + return (UINT16)MmioWriteWorker (Address, EfiCpuIoWidthUint16, Value); +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + return (UINT32)MmioReadWorker (Address, EfiCpuIoWidthUint32); +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + return (UINT32)MmioWriteWorker (Address, EfiCpuIoWidthUint32, Value); +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & 7) == 0); + return (UINT64)MmioReadWorker (Address, EfiCpuIoWidthUint64); +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & 7) == 0); + return (UINT64)MmioWriteWorker (Address, EfiCpuIoWidthUint64, Value); +} diff --git a/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c new file mode 100644 index 000000000..2731bcdac --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c @@ -0,0 +1,407 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeCpuIo2LibInternal.h" + +/** + Copy data from MMIO region to system memory by using 8-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 8-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = Buffer; + + while (Length-- > 0) { + *(Buffer++) = MmioRead8 (StartAddress++); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 16-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 16-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer. + +**/ +UINT16 * +EFIAPI +MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 32-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 32-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer. + +**/ +UINT32 * +EFIAPI +MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 64-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 64-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer. + +**/ +UINT64 * +EFIAPI +MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead64 (StartAddress); + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 8-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 8-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer. + +**/ +UINT8 * +EFIAPI +MmioWriteBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT8 *Buffer + ) +{ + VOID* ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = (UINT8 *) Buffer; + + while (Length-- > 0) { + MmioWrite8 (StartAddress++, *(Buffer++)); + } + + return ReturnBuffer; + +} + +/** + Copy data from system memory to MMIO region by using 16-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 16-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer. + +**/ +UINT16 * +EFIAPI +MmioWriteBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = (UINT16 *) Buffer; + + while (Length > 0) { + MmioWrite16 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 32-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 32-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer. + +**/ +UINT32 * +EFIAPI +MmioWriteBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = (UINT32 *) Buffer; + + while (Length > 0) { + MmioWrite32 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from system memory to MMIO region by using 64-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 64-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer. + +**/ +UINT64 * +EFIAPI +MmioWriteBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = (UINT64 *) Buffer; + + while (Length > 0) { + MmioWrite64 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + diff --git a/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c new file mode 100644 index 000000000..6e3e4e706 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c @@ -0,0 +1,1620 @@ +/** @file +Implementation of PcdLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +PCD_PROTOCOL *mPcd = NULL; +EFI_PCD_PROTOCOL *mPiPcd = NULL; +GET_PCD_INFO_PROTOCOL *mPcdInfo = NULL; +EFI_GET_PCD_INFO_PROTOCOL *mPiPcdInfo = NULL; + +/** + Retrieves the PI PCD protocol from the handle database. + + @retval EFI_PCD_PROTOCOL * The pointer to the EFI_PCD_PROTOCOL. +**/ +EFI_PCD_PROTOCOL * +EFIAPI +GetPiPcdProtocol ( + VOID + ) +{ + EFI_STATUS Status; + + if (mPiPcd == NULL) { + // + // PI Pcd protocol defined in PI 1.2 vol3 should be installed before the module + // access DynamicEx type PCD. + // + Status = gBS->LocateProtocol (&gEfiPcdProtocolGuid, NULL, (VOID **) &mPiPcd); + ASSERT_EFI_ERROR (Status); + ASSERT (mPiPcd != NULL); + } + return mPiPcd; +} + +/** + Retrieves the PCD protocol from the handle database. + + @retval PCD_PROTOCOL * The pointer to the PCD_PROTOCOL. +**/ +PCD_PROTOCOL * +EFIAPI +GetPcdProtocol ( + VOID + ) +{ + EFI_STATUS Status; + + if (mPcd == NULL) { + // + // PCD protocol need to be installed before the module access Dynamic type PCD. + // But dynamic type PCD is not required in PI 1.2 specification. + // + Status = gBS->LocateProtocol (&gPcdProtocolGuid, NULL, (VOID **)&mPcd); + ASSERT_EFI_ERROR (Status); + ASSERT (mPcd != NULL); + } + return mPcd; +} + +/** + Retrieves the PI PCD info protocol from the handle database. + + @retval EFI_GET_PCD_INFO_PROTOCOL * The pointer to the EFI_GET_PCD_INFO_PROTOCOL defined in PI 1.2.1 Vol 3. +**/ +EFI_GET_PCD_INFO_PROTOCOL * +GetPiPcdInfoProtocolPointer ( + VOID + ) +{ + EFI_STATUS Status; + + if (mPiPcdInfo == NULL) { + Status = gBS->LocateProtocol (&gEfiGetPcdInfoProtocolGuid, NULL, (VOID **)&mPiPcdInfo); + ASSERT_EFI_ERROR (Status); + ASSERT (mPiPcdInfo != NULL); + } + return mPiPcdInfo; +} + +/** + Retrieves the PCD info protocol from the handle database. + + @retval GET_PCD_INFO_PROTOCOL * The pointer to the GET_PCD_INFO_PROTOCOL. +**/ +GET_PCD_INFO_PROTOCOL * +GetPcdInfoProtocolPointer ( + VOID + ) +{ + EFI_STATUS Status; + + if (mPcdInfo == NULL) { + Status = gBS->LocateProtocol (&gGetPcdInfoProtocolGuid, NULL, (VOID **)&mPcdInfo); + ASSERT_EFI_ERROR (Status); + ASSERT (mPcdInfo != NULL); + } + return mPcdInfo; +} + +/** + This function provides a means by which SKU support can be established in the PCD infrastructure. + + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param SkuId The SKU value that will be used when the PCD service retrieves and sets values + associated with a PCD token. + + @return Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + GetPcdProtocol()->SetSku (SkuId); + + return SkuId; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->Get8 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->Get16 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->Get32 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->Get64 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->GetPtr (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->GetBool (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + return GetPcdProtocol()->GetSize (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Get8 (Guid, TokenNumber); +} + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Get16 (Guid, TokenNumber); +} + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Get32 (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Get64 (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->GetPtr (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->GetBool (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + Returns the size of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->GetSize (Guid, TokenNumber); +} + + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + GetPcdProtocol()->Set8 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + GetPcdProtocol()->Set16 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + GetPcdProtocol()->Set32 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + GetPcdProtocol()->Set64 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value + specified by Buffer and SizeOfBuffer. Buffer is returned. + If SizeOfBuffer is greater than the maximum size support by TokenNumber, + then set SizeOfBuffer to the maximum size supported by TokenNumber and + return NULL to indicate that the set operation was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and NULL must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN InputSizeOfBuffer; + + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + InputSizeOfBuffer = *SizeOfBuffer; + Status = GetPcdProtocol()->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer); + if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) { + return NULL; + } + + return (VOID *)Buffer; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + GetPcdProtocol()->SetBool (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (Guid != NULL); + + GetPiPcdProtocol()->Set8 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (Guid != NULL); + + GetPiPcdProtocol()->Set16 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (Guid != NULL); + + GetPiPcdProtocol()->Set32 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (Guid != NULL); + + GetPiPcdProtocol()->Set64 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size + supported by TokenNumber and return NULL to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN InputSizeOfBuffer; + + ASSERT (Guid != NULL); + + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + InputSizeOfBuffer = *SizeOfBuffer; + Status = GetPiPcdProtocol()->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer); + if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) { + return NULL; + } + + return Buffer; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (Guid != NULL); + + GetPiPcdProtocol()->SetBool (Guid, TokenNumber, Value); + + return Value; +} +#endif + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet8S ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return GetPcdProtocol()->Set8 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet16S ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return GetPcdProtocol()->Set16 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet32S ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return GetPcdProtocol()->Set32 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet64S ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return GetPcdProtocol()->Set64 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and EFI_INVALID_PARAMETER must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetPtrS ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + return GetPcdProtocol()->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetBoolS ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return GetPcdProtocol()->SetBool (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx8S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Set8 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx16S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Set16 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx32S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Set32 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx64S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->Set64 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExPtrS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + ASSERT (Guid != NULL); + + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + return GetPiPcdProtocol()->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExBoolS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (Guid != NULL); + + return GetPiPcdProtocol()->SetBool (Guid, TokenNumber, Value); +} + +/** + Set up a notification function that is called when a specified token is set. + + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = GetPiPcdProtocol()->CallbackOnSet (Guid, TokenNumber, (EFI_PCD_PROTOCOL_CALLBACK) NotificationFunction); + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + + Disable a notification function that was previously established with LibPcdCallbackOnSet(). + If NotificationFunction is NULL, then ASSERT(). + If LibPcdCallbackOnSet() was not previously called with Guid, TokenNumber, + and NotificationFunction, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = GetPiPcdProtocol()->CancelCallback (Guid, TokenNumber, (EFI_PCD_PROTOCOL_CALLBACK) NotificationFunction); + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Retrieves the next token in a token space. + + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. + + If TokenNumber is not 0 and is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] TokenNumber The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @return The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber + ) +{ + EFI_STATUS Status; + + Status = GetPiPcdProtocol()->GetNextToken (Guid, &TokenNumber); + ASSERT (!EFI_ERROR (Status) || TokenNumber == 0); + + return TokenNumber; +} + + + +/** + Used to retrieve the list of available PCD token space GUIDs. + + Returns the PCD token space GUID that follows TokenSpaceGuid in the list of token spaces + in the platform. + If TokenSpaceGuid is NULL, then a pointer to the first PCD token spaces returned. + If TokenSpaceGuid is the last PCD token space GUID in the list, then NULL is returned. + + @param TokenSpaceGuid The pointer to the a PCD token space GUID. + + @return The next valid token namespace. + +**/ +GUID * +EFIAPI +LibPcdGetNextTokenSpace ( + IN CONST GUID *TokenSpaceGuid + ) +{ + GetPiPcdProtocol()->GetNextTokenSpace (&TokenSpaceGuid); + + return (GUID *)TokenSpaceGuid; +} + + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtr ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return (VOID *) Buffer; +} + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrS ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return RETURN_SUCCESS; +} + + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtrAndSize ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return (VOID *) Buffer; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrAndSizeS ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return RETURN_SUCCESS; +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the default token space specified, then ASSERT(). + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfo ( + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + EFI_STATUS Status; + + Status = GetPcdInfoProtocolPointer()->GetInfo (TokenNumber, (EFI_PCD_INFO *) PcdInfo); + ASSERT_EFI_ERROR (Status); +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfoEx ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + EFI_STATUS Status; + + Status = GetPiPcdInfoProtocolPointer()->GetInfo (Guid, TokenNumber, (EFI_PCD_INFO *) PcdInfo); + ASSERT_EFI_ERROR (Status); +} + +/** + Retrieve the currently set SKU Id. + + @return The currently set SKU Id. If the platform has not set at a SKU Id, then the + default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU + Id is returned. +**/ +UINTN +EFIAPI +LibPcdGetSku ( + VOID + ) +{ + return GetPiPcdInfoProtocolPointer()->GetSku (); +} + diff --git a/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf new file mode 100644 index 000000000..3d4d21b44 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -0,0 +1,63 @@ +## @file +# Instance of PCD Library using PCD Protocol. +# +# There are two PCD protocols as follows: +# 1) PCD_PROTOCOL +# It is EDKII implementation which support Dynamic/DynamicEx Pcds. +# 2) EFI_PCD_PROTOCOL +# It is defined by PI specification 1.2, Vol 3 which only support dynamicEx +# type Pcd. +# +# For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL. +# +# This library instance uses the PCD_PROTOCOL to handle dynamic PCD request and use +# EFI_PCD_PROTOCOL to handle dynamicEx type PCD. +# +# Note: A driver of type DXE_RUNTIME_DRIVER and DXE_SMM_DRIVER can only use this DxePcdLib +# in their initialization without any issues to access Dynamic and DynamicEx PCD. They can't +# access Dynamic and DynamicEx PCD in the implementation of runtime services and SMI handlers. +# Because EFI_PCD_PROTOCOL is DXE protocol that is not available in OS runtime phase. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxePcdLib + MODULE_UNI_FILE = DxePcdLib.uni + FILE_GUID = af97eb89-4cc6-45f8-a514-ca025b346480 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PcdLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxePcdLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + UefiBootServicesTableLib + DebugLib + + +[Protocols] + gPcdProtocolGuid ## SOMETIMES_CONSUMES + gEfiPcdProtocolGuid ## CONSUMES + gGetPcdInfoProtocolGuid ## SOMETIMES_CONSUMES + gEfiGetPcdInfoProtocolGuid ## SOMETIMES_CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiPcdProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni new file mode 100644 index 000000000..c48aea35d --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni @@ -0,0 +1,26 @@ +// /** @file +// Instance of PCD Library using PCD Protocol. +// +// There are two PCD protocols as follows: +// 1) PCD_PROTOCOL +// It is EDKII implementation which support Dynamic/DynamicEx Pcds. +// 2) EFI_PCD_PROTOCOL +// It is defined by PI specification 1.2, Vol 3 which only support dynamicEx +// type Pcd. +// +// For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL. +// +// This library instance uses the PCD_PROTOCOL to handle dynamic PCD request and use +// EFI_PCD_PROTOCOL to handle dynamicEx type PCD. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCD Library using PCD Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "There are two PCD protocols: 1) PCD_PROTOCOL It is an EDKII implementation that supports Dynamic/DynamicEx PCDs. 2) EFI_PCD_PROTOCOL It is defined by PI Specification 1.2, Vol 3, which only support dynamicEx type PCD. For dynamicEx type PCDs, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL. This library instance uses the PCD_PROTOCOL to handle dynamic PCD requests and uses EFI_PCD_PROTOCOL to handle DynamicEx type PCDs." + diff --git a/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c new file mode 100644 index 000000000..cc79843b1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c @@ -0,0 +1,435 @@ +/** @file + DXE runtime Debug library instance based on Serial Port library. + It takes care not to call into SerialPortLib after ExitBootServices() has + been called, to prevent touching hardware that is no longer owned by the + firmware. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC EFI_EVENT mEfiExitBootServicesEvent; +STATIC BOOLEAN mEfiAtRuntime = FALSE; + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +// +// VA_LIST can not initialize to NULL for all compiler, so we use this to +// indicate a null VA_LIST +// +VA_LIST mVaListNull; + +/** + Set AtRuntime flag as TRUE after ExitBootServices. + + @param[in] Event The Event that is being processed. + @param[in] Context The Event Context. + +**/ +STATIC +VOID +EFIAPI +ExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mEfiAtRuntime = TRUE; +} + +/** + The constructor function to initialize the Serial Port library and + register a callback for the ExitBootServices event. + + @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 operation completed successfully. + @retval other Either the serial port failed to initialize or the + ExitBootServices event callback registration failed. +**/ +EFI_STATUS +EFIAPI +DxeRuntimeDebugLibSerialPortConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = SerialPortInitialize (); + if (EFI_ERROR (Status)) { + return Status; + } + + return SystemTable->BootServices->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, ExitBootServicesEvent, NULL, + &mEfiExitBootServicesEvent); +} + +/** + If a runtime driver exits with an error, it must call this routine + to free the allocated resource before the exiting. + + @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 Runtime Driver Lib shutdown successfully. + @retval EFI_UNSUPPORTED Runtime Driver lib was not initialized. +**/ +EFI_STATUS +EFIAPI +DxeRuntimeDebugLibSerialPortDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return SystemTable->BootServices->CloseEvent (mEfiExitBootServicesEvent); +} + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format 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, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled base on Null-terminated format string and a + VA_LIST argument list or a BASE_LIST argument list. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +DebugPrintMarker ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, + IN BASE_LIST BaseListMarker + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (mEfiAtRuntime) { + return; + } + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to an ASCII String + // + if (BaseListMarker == NULL) { + AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker); + } else { + AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker); + } + + // + // Send the print string to a Serial Port + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker); +} + + +/** + 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 The pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Ascii format + // + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", + gEfiCallerBaseName, FileName, LineNumber, Description); + + if (!mEfiAtRuntime) { + // + // Send the print string to the Console Output device + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); + } + + // + // 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 The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + 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/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf new file mode 100644 index 000000000..31d169ad7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf @@ -0,0 +1,47 @@ +## @file +# DXE runtime Debug library instance based on Serial Port library. +# It takes care not to call into SerialPortLib after ExitBootServices() has +# been called, to prevent touching hardware that is no longer owned by the +# firmware. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = DxeRuntimeDebugLibSerialPort + MODULE_UNI_FILE = DxeRuntimeDebugLibSerialPort.uni + FILE_GUID = 9D914E2F-7CCB-41DB-8E74-9AFF8F3BBFBF + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|DXE_RUNTIME_DRIVER + CONSTRUCTOR = DxeRuntimeDebugLibSerialPortConstructor + DESTRUCTOR = DxeRuntimeDebugLibSerialPortDestructor + +# +# VALID_ARCHITECTURES = AARCH64 ARM IA32 X64 EBC +# + +[Sources] + DebugLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugPrintErrorLevelLib + PcdLib + PrintLib + SerialPortLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni new file mode 100644 index 000000000..ddb76a9fa --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni @@ -0,0 +1,16 @@ +// /** @file +// DXE runtime Debug library instance based on Serial Port library. +// It takes care not to call into SerialPortLib after ExitBootServices() has +// been called, to prevent touching hardware that is no longer owned by the +// firmware. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "DXE runtime Debug library instance based on Serial Port library" + +#string STR_MODULE_DESCRIPTION #language en-US "It takes care not to call into SerialPortLib after ExitBootServices() has been called." diff --git a/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf new file mode 100644 index 000000000..8d2ba1d18 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf @@ -0,0 +1,49 @@ +## @file +# Instance of PCI Express Library using the 256 MB PCI Express MMIO window that +# is safe for runtime use. +# +# PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +# PCI Configuration cycles. Layers on top of an I/O Library instance. A table of +# PCI devices that are registered for for runtime access is maintained so the +# proper virtual address is used to perform the PCI Express Configuration cycle. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeRuntimePciExpressLib + MODULE_UNI_FILE = DxeRuntimePciExpressLib.uni + FILE_GUID = 54DCBCE5-92AD-41f5-AAAF-1170F16DA6A8 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciExpressLib|DXE_RUNTIME_DRIVER + CONSTRUCTOR = DxeRuntimePciExpressLibConstructor + DESTRUCTOR = DxeRuntimePciExpressLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciExpressLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + DebugLib + PcdLib + MemoryAllocationLib + UefiBootServicesTableLib + DxeServicesTableLib + UefiRuntimeLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni new file mode 100644 index 000000000..ddd877b57 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni @@ -0,0 +1,21 @@ +// /** @file +// Instance of PCI Express Library using the 256 MB PCI Express MMIO window that +// +// is safe for runtime use. +// +// PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +// PCI Configuration cycles. Layers on top of an I/O Library instance. A table of +// PCI devices that are registered for for runtime access is maintained so the +// proper virtual address is used to perform the PCI Express Configuration cycle. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCI Express Support Library" + +#string STR_MODULE_DESCRIPTION #language en-US "The PCI Express Library uses a 256 MB PCI Express MMIO window to perform PCI Configuration cycles. This library layers on top of an I/O Library instance. A table of PCI devices that are registered for runtime access is maintained so that the proper virtual address is used to perform the PCI Express Configuration cycle." + diff --git a/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c new file mode 100644 index 000000000..b89954351 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c @@ -0,0 +1,1653 @@ +/** @file + Functions in this library instance make use of MMIO functions in IoLib to + access memory mapped PCI configuration space. + + All assertions for I/O operations are handled in MMIO functions in the IoLib + Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime +/// +typedef struct { + UINTN PhysicalAddress; + UINTN VirtualAddress; +} PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE; + +/// +/// Set Virtual Address Map Event +/// +EFI_EVENT mDxeRuntimePciExpressLibVirtualNotifyEvent = NULL; + +/// +/// Module global that contains the base physical address of the PCI Express MMIO range. +/// +UINTN mDxeRuntimePciExpressLibPciExpressBaseAddress = 0; + +/// +/// The number of PCI devices that have been registered for runtime access. +/// +UINTN mDxeRuntimePciExpressLibNumberOfRuntimeRanges = 0; + +/// +/// The table of PCI devices that have been registered for runtime access. +/// +PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE *mDxeRuntimePciExpressLibRegistrationTable = NULL; + +/// +/// The table index of the most recent virtual address lookup. +/// +UINTN mDxeRuntimePciExpressLibLastRuntimeRange = 0; + + +/** + Convert the physical PCI Express MMIO addresses for all registered PCI devices + to virtual addresses. + + @param[in] Event The event that is being processed. + @param[in] Context The Event Context. +**/ +VOID +EFIAPI +DxeRuntimePciExpressLibVirtualNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + + // + // If there have been no runtime registrations, then just return + // + if (mDxeRuntimePciExpressLibRegistrationTable == NULL) { + return; + } + + // + // Convert physical addresses associated with the set of registered PCI devices to + // virtual addresses. + // + for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) { + EfiConvertPointer (0, (VOID **) &(mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress)); + } + + // + // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address. + // + EfiConvertPointer (0, (VOID **) &mDxeRuntimePciExpressLibRegistrationTable); +} + +/** + The constructor function caches the PCI Express Base Address and creates a + Set Virtual Address Map event to convert physical address to virtual addresses. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor completed successfully. + @retval Other value The constructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciExpressLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Cache the physical address of the PCI Express MMIO range into a module global variable + // + mDxeRuntimePciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress); + + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + TPL_NOTIFY, + DxeRuntimePciExpressLibVirtualNotify, + NULL, + &mDxeRuntimePciExpressLibVirtualNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + The destructor function frees any allocated buffers and closes the Set Virtual + Address Map event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciExpressLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // If one or more PCI devices have been registered for runtime access, then + // free the registration table. + // + if (mDxeRuntimePciExpressLibRegistrationTable != NULL) { + FreePool (mDxeRuntimePciExpressLibRegistrationTable); + } + + // + // Close the Set Virtual Address Map event + // + Status = gBS->CloseEvent (mDxeRuntimePciExpressLibVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Gets the base address of PCI Express. + + This internal functions retrieves PCI Express Base Address via a PCD entry + PcdPciExpressBaseAddress. + + @param Address The address that encodes the PCI Bus, Device, Function and Register. + @return The base address of PCI Express. + +**/ +UINTN +GetPciExpressAddress ( + IN UINTN Address + ) +{ + UINTN Index; + + // + // Make sure Address is valid + // + ASSERT (((Address) & ~0xfffffff) == 0); + + // + // Convert Address to a physical address in the MMIO PCI Express range + // + Address += mDxeRuntimePciExpressLibPciExpressBaseAddress; + + // + // If SetVirtualAddressMap() has not been called, then just return the physical address + // + if (!EfiGoneVirtual ()) { + return Address; + } + + // + // See if there is a physical address match at the exact same index as the last address match + // + if (mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].PhysicalAddress == (Address & (~0x00000fff))) { + // + // Convert the physical address to a virtual address and return the virtual address + // + return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].VirtualAddress; + } + + // + // Search the entire table for a physical address match + // + for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) { + if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == (Address & (~0x00000fff))) { + // + // Cache the matching index value + // + mDxeRuntimePciExpressLibLastRuntimeRange = Index; + // + // Convert the physical address to a virtual address and return the virtual address + // + return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress; + } + } + + // + // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint. + // + ASSERT (FALSE); + CpuBreakpoint(); + + // + // Return the physical address + // + return Address; +} + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration + registers associated with that PCI device may be accessed after SetVirtualAddressMap() + is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciExpressRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Index; + VOID *NewTable; + + // + // Return an error if this function is called after ExitBootServices(). + // + if (EfiAtRuntime ()) { + return RETURN_UNSUPPORTED; + } + + // + // Make sure Address is valid + // + ASSERT (((Address) & ~0xfffffff) == 0); + + // + // Convert Address to a physical address in the MMIO PCI Express range + // at the beginning of the PCI Configuration header for the specified + // PCI Bus/Dev/Func + // + Address = GetPciExpressAddress (Address & 0x0ffff000); + + // + // See if Address has already been registered for runtime access + // + for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) { + if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == Address) { + return RETURN_SUCCESS; + } + } + + // + // Get the GCD Memory Descriptor for the PCI Express Bus/Dev/Func specified by Address + // + Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS + // will allocate a virtual address range for the 4KB PCI Configuration Header. + // + Status = gDS->SetMemorySpaceAttributes (Address, 0x1000, Descriptor.Attributes | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Grow the size of the registration table + // + NewTable = ReallocateRuntimePool ( + (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 0) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE), + (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 1) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE), + mDxeRuntimePciExpressLibRegistrationTable + ); + if (NewTable == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + mDxeRuntimePciExpressLibRegistrationTable = NewTable; + mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].PhysicalAddress = Address; + mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].VirtualAddress = Address; + mDxeRuntimePciExpressLibNumberOfRuntimeRanges++; + + return RETURN_SUCCESS; +} + + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ) +{ + return MmioRead8 (GetPciExpressAddress (Address)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return MmioWrite8 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioOr8 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioAnd8 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioAndThenOr8 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioBitFieldWrite8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioBitFieldOr8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioBitFieldAnd8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioBitFieldAndThenOr8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ) +{ + return MmioRead16 (GetPciExpressAddress (Address)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return MmioWrite16 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioOr16 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioAnd16 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioAndThenOr16 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioBitFieldWrite16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioBitFieldOr16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioBitFieldAnd16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioBitFieldAndThenOr16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ) +{ + return MmioRead32 (GetPciExpressAddress (Address)); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return MmioWrite32 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioOr32 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioAnd32 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioAndThenOr32 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioBitFieldWrite32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioBitFieldOr32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioBitFieldAnd32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioBitFieldAndThenOr32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size read data from StartAddress. + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + // + // Make sure Address is valid + // + ASSERT (((StartAddress) & ~0xfffffff) == 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress)); + + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAddress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + // + // Make sure Address is valid + // + ASSERT (((StartAddress) & ~0xfffffff) == 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/DxeServicesLib/Allocate.c b/roms/edk2/MdePkg/Library/DxeServicesLib/Allocate.c new file mode 100644 index 000000000..efb65768b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesLib/Allocate.c @@ -0,0 +1,48 @@ +/** @file + DxeServicesLib memory allocation routines + + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Allocates one or more 4KB pages of a given type from a memory region that is + accessible to PEI. + + Allocates the number of 4KB pages of type 'MemoryType' and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB + boundary. If Pages is 0, then NULL is returned. If there is not enough + memory remaining to satisfy the request, then NULL is returned. + + @param[in] MemoryType The memory type to allocate + @param[in] Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePeiAccessiblePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *)(UINTN)Memory; +} diff --git a/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c new file mode 100644 index 000000000..3e3bbf605 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c @@ -0,0 +1,1092 @@ +/** @file + MDE DXE Services Library provides functions that simplify the development of DXE Drivers. + These functions help access data from sections of FFS files or from file path. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Identify the device handle from which the Image is loaded from. As this device handle is passed to + GetSectionFromFv as the identifier for a Firmware Volume, an EFI_FIRMWARE_VOLUME2_PROTOCOL + protocol instance should be located successfully by calling gBS->HandleProtocol (). + + This function locates the EFI_LOADED_IMAGE_PROTOCOL instance installed + on ImageHandle. It then returns EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle. + + If ImageHandle is NULL, then ASSERT (); + If failed to locate a EFI_LOADED_IMAGE_PROTOCOL on ImageHandle, then ASSERT (); + + @param ImageHandle The firmware allocated handle for UEFI image. + + @retval EFI_HANDLE The device handle from which the Image is loaded from. + +**/ +EFI_HANDLE +InternalImageHandleToFvHandle ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + ASSERT (ImageHandle != NULL); + + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + ASSERT_EFI_ERROR (Status); + + // + // The LoadedImage->DeviceHandle may be NULL. + // For example for DxeCore, there is LoadedImage protocol installed for it, but the + // LoadedImage->DeviceHandle could not be initialized before the FV2 (contain DxeCore) + // protocol is installed. + // + return LoadedImage->DeviceHandle; + +} + +/** + Allocate and fill a buffer from a Firmware Section identified by a Firmware File GUID name, a Firmware + Section type and instance number from the specified Firmware Volume. + + This functions first locate the EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance on FvHandle in order to + carry out the Firmware Volume read operation. The function then reads the Firmware Section found specified + by NameGuid, SectionType and SectionInstance. + + The details of this search order is defined in description of EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection () + found in PI Specification. + + If SectionType is EFI_SECTION_TE, EFI_SECTION_TE is used as section type to start the search. If EFI_SECTION_TE section + is not found, EFI_SECTION_PE32 will be used to try the search again. If no EFI_SECTION_PE32 section is found, EFI_NOT_FOUND + is returned. + + The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated + by this function. This function can be only called at TPL_NOTIFY and below. + + If NameGuid is NULL, then ASSERT(); + If Buffer is NULL, then ASSERT(); + If Size is NULL, then ASSERT(). + + @param FvHandle The device handle that contains a instance of + EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + @param NameGuid The GUID name of a Firmware File. + @param SectionType The Firmware Section type. + @param SectionInstance The instance number of Firmware Section to + read from starting from 0. + @param Buffer On output, Buffer contains the data read + from the section in the Firmware File found. + @param Size On output, the size of Buffer. + + @retval EFI_SUCCESS The image is found and data and size is returned. + @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType + can't be found. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + output data buffer or complete the operations. + @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the + Firmware Volume. + @retval EFI_ACCESS_DENIED The firmware volume containing the searched + Firmware File is configured to disallow reads. + +**/ +EFI_STATUS +InternalGetSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINT32 AuthenticationStatus; + + ASSERT (NameGuid != NULL); + ASSERT (Buffer != NULL); + ASSERT (Size != NULL); + + if (FvHandle == NULL) { + // + // Return EFI_NOT_FOUND directly for NULL FvHandle. + // + return EFI_NOT_FOUND; + } + + Status = gBS->HandleProtocol ( + FvHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Read desired section content in NameGuid file + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + SectionType, + SectionInstance, + Buffer, + Size, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) { + // + // Try reading PE32 section, if the required section is TE type + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + EFI_SECTION_PE32, + SectionInstance, + Buffer, + Size, + &AuthenticationStatus + ); + } + + return Status; +} + +/** + Searches all the available firmware volumes and returns the first matching FFS section. + + This function searches all the firmware volumes for FFS files with FV file type specified by FileType + The order that the firmware volumes is searched is not deterministic. For each available FV a search + is made for FFS file of type FileType. If the FV contains more than one FFS file with the same FileType, + the FileInstance instance will be the matched FFS file. For each FFS file found a search + is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances + of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocated buffer. + See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections + are retrieved from an FFS file based on SectionType and SectionInstance. + + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + @param FileType Indicates the FV file type to search for within all + available FVs. + @param FileInstance Indicates which file instance within all available + FVs specified by FileType. + FileInstance starts from zero. + @param SectionType Indicates the FFS section type to search for + within the FFS file + specified by FileType with FileInstance. + @param SectionInstance Indicates which section instance within the FFS file + specified by FileType with FileInstance to retrieve. + SectionInstance starts from zero. + @param Buffer On output, a pointer to a callee allocated buffer + containing the FFS file section that was found. + Is it the caller's responsibility to free this + buffer using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve + the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a + device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because + the firmware volume that + contains the matching FFS section does not allow reads. +**/ +EFI_STATUS +EFIAPI +GetSectionFromAnyFvByFileType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN FileInstance, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN IndexFv; + UINTN IndexFile; + UINTN Key; + EFI_GUID NameGuid; + EFI_FV_FILE_ATTRIBUTES Attributes; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + + ASSERT (Buffer != NULL); + ASSERT (Size != NULL); + + // + // Locate all available FVs. + // + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Go through FVs one by one to find the required section data. + // + for (IndexFv = 0; IndexFv < HandleCount; IndexFv++) { + Status = gBS->HandleProtocol ( + HandleBuffer[IndexFv], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&Fv + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Use Firmware Volume 2 Protocol to search for a file of type FileType in all FVs. + // + IndexFile = FileInstance + 1; + Key = 0; + do { + Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, Size); + if (EFI_ERROR (Status)) { + break; + } + IndexFile --; + } while (IndexFile > 0); + + // + // Fv File with the required FV file type is found. + // Search the section file in the found FV file. + // + if (IndexFile == 0) { + Status = InternalGetSectionFromFv ( + HandleBuffer[IndexFv], + &NameGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); + + if (!EFI_ERROR (Status)) { + goto Done; + } + } + } + + // + // The required FFS section file is not found. + // + if (IndexFv == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + return Status; +} + +/** + Searches all the availables firmware volumes and returns the first matching FFS section. + + This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid. + The order that the firmware volumes is searched is not deterministic. For each FFS file found a search + is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances + of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocated buffer. + See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections + are retrieved from an FFS file based on SectionType and SectionInstance. + + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If NameGuid is NULL, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + + @param NameGuid A pointer to to the FFS filename GUID to search for + within any of the firmware volumes in the platform. + @param SectionType Indicates the FFS section type to search for within + the FFS file specified by NameGuid. + @param SectionInstance Indicates which section instance within the FFS file + specified by NameGuid to retrieve. + @param Buffer On output, a pointer to a callee allocated buffer + containing the FFS file section that was found. + Is it the caller's responsibility to free this buffer + using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to + retrieve the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a + device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the + firmware volume that + contains the matching FFS section does not allow reads. +**/ +EFI_STATUS +EFIAPI +GetSectionFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE FvHandle; + + // + // Search the FV that contain the caller's FFS first. + // FV builder can choose to build FFS into the this FV + // so that this implementation of GetSectionFromAnyFv + // will locate the FFS faster. + // + FvHandle = InternalImageHandleToFvHandle (gImageHandle); + Status = InternalGetSectionFromFv ( + FvHandle, + NameGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // Skip the FV that contain the caller's FFS + // + if (HandleBuffer[Index] != FvHandle) { + Status = InternalGetSectionFromFv ( + HandleBuffer[Index], + NameGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); + + if (!EFI_ERROR (Status)) { + goto Done; + } + } + + } + + if (Index == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + return Status; + +} + +/** + Searches the firmware volume that the currently executing module was loaded from and returns the first matching FFS section. + + This function searches the firmware volume that the currently executing module was loaded + from for an FFS file with an FFS filename specified by NameGuid. If the FFS file is found a search + is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance + instances of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocated buffer. + See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections are retrieved from + an FFS file based on SectionType and SectionInstance. + + If the currently executing module was not loaded from a firmware volume, then EFI_NOT_FOUND is returned. + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + + This function must be called with a TPL <= TPL_NOTIFY. + If NameGuid is NULL, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + @param NameGuid A pointer to to the FFS filename GUID to search for + within the firmware volumes that the currently + executing module was loaded from. + @param SectionType Indicates the FFS section type to search for within + the FFS file specified by NameGuid. + @param SectionInstance Indicates which section instance within the FFS file + specified by NameGuid to retrieve. + @param Buffer On output, a pointer to a callee allocated buffer + containing the FFS file section that was found. + Is it the caller's responsibility to free this buffer + using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve + the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a + device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the + firmware volume that contains the matching FFS + section does not allow reads. +**/ +EFI_STATUS +EFIAPI +GetSectionFromFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + return InternalGetSectionFromFv ( + InternalImageHandleToFvHandle(gImageHandle), + NameGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); +} + + +/** + Searches the FFS file the currently executing module was loaded from and returns the first matching FFS section. + + This function searches the FFS file that the currently executing module was loaded from for a FFS sections of type SectionType. + If the FFS file contains at least SectionInstance instances of the FFS section specified by SectionType, + then the SectionInstance instance is returned in Buffer. Buffer is allocated using AllocatePool(), + and the size of the allocated buffer is returned in Size. It is the caller's responsibility + to use FreePool() to free the allocated buffer. See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for + details on how sections are retrieved from an FFS file based on SectionType and SectionInstance. + + If the currently executing module was not loaded from an FFS file, then EFI_NOT_FOUND is returned. + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + + @param SectionType Indicates the FFS section type to search for within + the FFS file that the currently executing module + was loaded from. + @param SectionInstance Indicates which section instance to retrieve within + the FFS file that the currently executing module + was loaded from. + @param Buffer On output, a pointer to a callee allocated buffer + containing the FFS file section that was found. + Is it the caller's responsibility to free this buffer + using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve + the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a + device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the + firmware volume that contains the matching FFS + section does not allow reads. + +**/ +EFI_STATUS +EFIAPI +GetSectionFromFfs ( + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + return InternalGetSectionFromFv( + InternalImageHandleToFvHandle(gImageHandle), + &gEfiCallerIdGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); +} + + +/** + Get the image file buffer data and buffer size by its device path. + + Access the file either from a firmware volume, from a file system interface, + or from the load file interface. + + Allocate memory to store the found image. The caller is responsible to free memory. + + If FilePath is NULL, then NULL is returned. + If FileSize is NULL, then NULL is returned. + If AuthenticationStatus is NULL, then NULL is returned. + + @param[in] BootPolicy Policy for Open Image File.If TRUE, indicates + that the request originates from the boot + manager, and that the boot manager is + attempting to load FilePath as a boot + selection. If FALSE, then FilePath must + match an exact file to be loaded. + @param[in] FilePath The pointer to the device path of the file + that is abstracted to the file buffer. + @param[out] FileSize The pointer to the size of the abstracted + file buffer. + @param[out] AuthenticationStatus Pointer to the authentication status. + + @retval NULL FilePath is NULL, or FileSize is NULL, or AuthenticationStatus is NULL, or the file can't be found. + @retval other The abstracted file buffer. The caller is responsible to free memory. +**/ +VOID * +EFIAPI +GetFileBufferByFilePath ( + IN BOOLEAN BootPolicy, + IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath, + OUT UINTN *FileSize, + OUT UINT32 *AuthenticationStatus + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; + EFI_HANDLE Handle; + EFI_GUID *FvNameGuid; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + EFI_SECTION_TYPE SectionType; + UINT8 *ImageBuffer; + UINTN ImageBufferSize; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES Attrib; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE FileHandle; + EFI_FILE_HANDLE LastHandle; + EFI_FILE_INFO *FileInfo; + UINTN FileInfoSize; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + EFI_LOAD_FILE2_PROTOCOL *LoadFile2; + EFI_STATUS Status; + + // + // Check input File device path. + // + if (FilePath == NULL || FileSize == NULL || AuthenticationStatus == NULL) { + return NULL; + } + + // + // Init local variable + // + TempDevicePathNode = NULL; + FvNameGuid = NULL; + FileInfo = NULL; + FileHandle = NULL; + ImageBuffer = NULL; + ImageBufferSize = 0; + *AuthenticationStatus = 0; + + // + // Copy File Device Path + // + OrigDevicePathNode = DuplicateDevicePath (FilePath); + if (OrigDevicePathNode == NULL) { + return NULL; + } + + // + // Check whether this device path support FV2 protocol. + // Is so, this device path may contain a Image. + // + DevicePathNode = OrigDevicePathNode; + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle); + if (!EFI_ERROR (Status)) { + // + // For FwVol File system there is only a single file name that is a GUID. + // + FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePathNode); + if (FvNameGuid == NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + // + // Read image from the firmware file + // + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol); + if (!EFI_ERROR (Status)) { + SectionType = EFI_SECTION_PE32; + ImageBuffer = NULL; + Status = FwVol->ReadSection ( + FwVol, + FvNameGuid, + SectionType, + 0, + (VOID **)&ImageBuffer, + &ImageBufferSize, + AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Try a raw file, since a PE32 SECTION does not exist + // + if (ImageBuffer != NULL) { + FreePool (ImageBuffer); + *AuthenticationStatus = 0; + } + ImageBuffer = NULL; + Status = FwVol->ReadFile ( + FwVol, + FvNameGuid, + (VOID **)&ImageBuffer, + &ImageBufferSize, + &Type, + &Attrib, + AuthenticationStatus + ); + } + } + } + if (!EFI_ERROR (Status)) { + goto Finish; + } + } + + // + // Attempt to access the file via a file system interface + // + DevicePathNode = OrigDevicePathNode; + Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &DevicePathNode, &Handle); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&Volume); + if (!EFI_ERROR (Status)) { + // + // Open the Volume to get the File System handle + // + Status = Volume->OpenVolume (Volume, &FileHandle); + if (!EFI_ERROR (Status)) { + // + // Duplicate the device path to avoid the access to unaligned device path node. + // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH + // nodes, It assures the fields in device path nodes are 2 byte aligned. + // + TempDevicePathNode = DuplicateDevicePath (DevicePathNode); + if (TempDevicePathNode == NULL) { + FileHandle->Close (FileHandle); + // + // Setting Status to an EFI_ERROR value will cause the rest of + // the file system support below to be skipped. + // + Status = EFI_OUT_OF_RESOURCES; + } + // + // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the + // directory information and filename can be separate. The goal is to inch + // our way down each device path node and close the previous node + // + DevicePathNode = TempDevicePathNode; + while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) { + if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH || + DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) { + Status = EFI_UNSUPPORTED; + break; + } + + LastHandle = FileHandle; + FileHandle = NULL; + + Status = LastHandle->Open ( + LastHandle, + &FileHandle, + ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName, + EFI_FILE_MODE_READ, + 0 + ); + + // + // Close the previous node + // + LastHandle->Close (LastHandle); + + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + if (!EFI_ERROR (Status)) { + // + // We have found the file. Now we need to read it. Before we can read the file we need to + // figure out how big the file is. + // + FileInfo = NULL; + FileInfoSize = 0; + Status = FileHandle->GetInfo ( + FileHandle, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileInfo = AllocatePool (FileInfoSize); + if (FileInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = FileHandle->GetInfo ( + FileHandle, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo + ); + } + } + + if (!EFI_ERROR (Status) && (FileInfo != NULL)) { + if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + // + // Allocate space for the file + // + ImageBuffer = AllocatePool ((UINTN)FileInfo->FileSize); + if (ImageBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + // + // Read the file into the buffer we allocated + // + ImageBufferSize = (UINTN)FileInfo->FileSize; + Status = FileHandle->Read (FileHandle, &ImageBufferSize, ImageBuffer); + } + } + } + } + // + // Close the file and Free FileInfo and TempDevicePathNode since we are done + // + if (FileInfo != NULL) { + FreePool (FileInfo); + } + if (FileHandle != NULL) { + FileHandle->Close (FileHandle); + } + if (TempDevicePathNode != NULL) { + FreePool (TempDevicePathNode); + } + } + } + if (!EFI_ERROR (Status)) { + goto Finish; + } + } + + // + // Attempt to access the file via LoadFile2 interface + // + if (!BootPolicy) { + DevicePathNode = OrigDevicePathNode; + Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePathNode, &Handle); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (Handle, &gEfiLoadFile2ProtocolGuid, (VOID**)&LoadFile2); + if (!EFI_ERROR (Status)) { + // + // Call LoadFile2 with the correct buffer size + // + ImageBufferSize = 0; + ImageBuffer = NULL; + Status = LoadFile2->LoadFile ( + LoadFile2, + DevicePathNode, + FALSE, + &ImageBufferSize, + ImageBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ImageBuffer = AllocatePool (ImageBufferSize); + if (ImageBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = LoadFile2->LoadFile ( + LoadFile2, + DevicePathNode, + FALSE, + &ImageBufferSize, + ImageBuffer + ); + } + } + } + if (!EFI_ERROR (Status)) { + goto Finish; + } + } + } + + // + // Attempt to access the file via LoadFile interface + // + DevicePathNode = OrigDevicePathNode; + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &DevicePathNode, &Handle); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID**)&LoadFile); + if (!EFI_ERROR (Status)) { + // + // Call LoadFile with the correct buffer size + // + ImageBufferSize = 0; + ImageBuffer = NULL; + Status = LoadFile->LoadFile ( + LoadFile, + DevicePathNode, + BootPolicy, + &ImageBufferSize, + ImageBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ImageBuffer = AllocatePool (ImageBufferSize); + if (ImageBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = LoadFile->LoadFile ( + LoadFile, + DevicePathNode, + BootPolicy, + &ImageBufferSize, + ImageBuffer + ); + } + } + } + } + +Finish: + + if (EFI_ERROR (Status)) { + if (ImageBuffer != NULL) { + FreePool (ImageBuffer); + ImageBuffer = NULL; + } + *FileSize = 0; + } else { + *FileSize = ImageBufferSize; + } + + FreePool (OrigDevicePathNode); + + return ImageBuffer; +} + +/** + Searches all the available firmware volumes and returns the file device path of first matching + FFS section. + + This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid. + The order that the firmware volumes is searched is not deterministic. For each FFS file found a search + is made for FFS sections of type SectionType. + + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If NameGuid is NULL, then ASSERT(). + + @param NameGuid A pointer to to the FFS filename GUID to search for + within any of the firmware volumes in the platform. + @param SectionType Indicates the FFS section type to search for within + the FFS file specified by NameGuid. + @param SectionInstance Indicates which section instance within the FFS file + specified by NameGuid to retrieve. + @param FvFileDevicePath Device path for the target FFS + file. + + @retval EFI_SUCCESS The specified file device path of FFS section was returned. + @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a + device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the + firmware volume that contains the matching FFS section does not + allow reads. + @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL. + +**/ +EFI_STATUS +EFIAPI +GetFileDevicePathFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE FvHandle; + EFI_DEVICE_PATH_PROTOCOL *FvDevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *TempFvFileDevicePath; + VOID *Buffer; + UINTN Size; + + if (FvFileDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + HandleBuffer = NULL; + FvDevicePath = NULL; + TempFvFileDevicePath = NULL; + Buffer = NULL; + Size = 0; + + // + // Search the FV that contain the caller's FFS first. + // FV builder can choose to build FFS into the this FV + // so that this implementation of GetSectionFromAnyFv + // will locate the FFS faster. + // + FvHandle = InternalImageHandleToFvHandle (gImageHandle); + Status = InternalGetSectionFromFv ( + FvHandle, + NameGuid, + SectionType, + SectionInstance, + &Buffer, + &Size + ); + if (!EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // Skip the FV that contain the caller's FFS + // + if (HandleBuffer[Index] != FvHandle) { + Status = InternalGetSectionFromFv ( + HandleBuffer[Index], + NameGuid, + SectionType, + SectionInstance, + &Buffer, + &Size + ); + + if (!EFI_ERROR (Status)) { + // + // Update FvHandle to the current handle. + // + FvHandle = HandleBuffer[Index]; + goto Done; + } + } + } + + if (Index == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + if (Status == EFI_SUCCESS) { + // + // Build a device path to the file in the FV to pass into gBS->LoadImage + // + Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + if (EFI_ERROR (Status)) { + *FvFileDevicePath = NULL; + } else { + TempFvFileDevicePath = AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + END_DEVICE_PATH_LENGTH); + if (TempFvFileDevicePath == NULL) { + *FvFileDevicePath = NULL; + return EFI_OUT_OF_RESOURCES; + } + EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)TempFvFileDevicePath, NameGuid); + SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath)); + *FvFileDevicePath = AppendDevicePath ( + FvDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)TempFvFileDevicePath + ); + FreePool (TempFvFileDevicePath); + } + } + + if (Buffer != NULL) { + FreePool (Buffer); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return Status; +} diff --git a/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf new file mode 100644 index 000000000..ec3e8711c --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf @@ -0,0 +1,60 @@ +## @file +# DXE Services Library instance provides functions that simplify the development of DXE Drivers. +# +# DXE Services Library provides access data from sections of FFS files based on FV protocol. +# It also provides access file based on file path from a firmware volume, +# from a file system interface, or from the load file interface. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeServicesLib + MODULE_UNI_FILE = DxeServicesLib.uni + FILE_GUID = EE680C58-FFC0-4a5d-858F-66FF9C84BC9F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DxeServicesLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64 +# + +[Sources] + DxeServicesLib.c + +[Sources.IA32, Sources.EBC, Sources.ARM, Sources.AARCH64, Sources.RISCV64] + Allocate.c + +[Sources.X64] + X64/Allocate.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + DebugLib + DevicePathLib + UefiLib + UefiBootServicesTableLib + +[LibraryClasses.X64] + HobLib + +[Guids] + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Protocols] + gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadFileProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadFile2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + diff --git a/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni new file mode 100644 index 000000000..9f1036218 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni @@ -0,0 +1,18 @@ +// /** @file +// DXE Services Library instance provides functions that simplify the development of DXE Drivers. +// +// DXE Services Library provides access data from sections of FFS files based on FV protocol. +// It also provides access file based on file path from a firmware volume, +// from a file system interface, or from the load file interface. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Provides functions that simplify the development of DXE Drivers" + +#string STR_MODULE_DESCRIPTION #language en-US "A DXE Services Library provides access data from sections of FFS files based on FV protocol. It also provides access file based on file path from a firmware volume, from a file system interface, or from the load file interface." + diff --git a/roms/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c b/roms/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c new file mode 100644 index 000000000..41c4cea39 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c @@ -0,0 +1,63 @@ +/** @file + DxeServicesLib memory allocation routines + + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +/** + Allocates one or more 4KB pages of a given type from a memory region that is + accessible to PEI. + + Allocates the number of 4KB pages of type 'MemoryType' and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB + boundary. If Pages is 0, then NULL is returned. If there is not enough + memory remaining to satisfy the request, then NULL is returned. + + @param[in] MemoryType The memory type to allocate + @param[in] Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePeiAccessiblePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_ALLOCATE_TYPE AllocType; + EFI_PHYSICAL_ADDRESS Memory; + EFI_HOB_HANDOFF_INFO_TABLE *PhitHob; + + if (Pages == 0) { + return NULL; + } + + AllocType = AllocateAnyPages; + // + // A X64 build of DXE may be combined with a 32-bit build of PEI, and so we + // need to check the memory limit set by PEI, and allocate below 4 GB if the + // limit is set to 4 GB or lower. + // + PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)GetHobList (); + if (PhitHob->EfiFreeMemoryTop <= MAX_UINT32) { + AllocType = AllocateMaxAddress; + Memory = MAX_UINT32; + } + + Status = gBS->AllocatePages (AllocType, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *)(UINTN)Memory; +} diff --git a/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c new file mode 100644 index 000000000..9acb1b79b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c @@ -0,0 +1,62 @@ +/** @file + This library implement library class DxeServiceTableLib. + It produce EFI_DXE_SERVICE pointer in global variable gDS in library's constructure. + + A DXE driver can use gDS pointer to access services in EFI_DXE_SERVICE, if this + DXE driver declare that use DxeServicesTableLib library class and link to this + library instance. + + Please attention this library instance can not be used util EFI_SYSTEM_TABLE was + initialized. + + This library contains construct function to retrieve EFI_DXE_SERVICE, this construct + function will be invoked in DXE driver's autogen file. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +// +// Cache copy of the DXE Services Table +// +EFI_DXE_SERVICES *gDS = NULL; + +/** + The constructor function caches the pointer of DXE Services Table. + + The constructor function caches the pointer of DXE Services Table. + It will ASSERT() if that operation fails. + It will ASSERT() if the pointer of DXE Services Table is NULL. + 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 +DxeServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Cache copy of the DXE Services Table + // + Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); + ASSERT_EFI_ERROR (Status); + ASSERT (gDS != NULL); + + return Status; +} diff --git a/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf new file mode 100644 index 000000000..536e615ae --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf @@ -0,0 +1,44 @@ +## @file +# Instance of DXE Services Table Library using EFI Configuration Table. +# +# DXE Services Table Library that retrieves a pointer to the DXE Services +# Table from the Configuration Table in the EFI System Table. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeServicesTableLib + MODULE_UNI_FILE = DxeServicesTableLib.uni + FILE_GUID = baa1baa3-0a8d-402c-8042-985115fae953 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DxeServicesTableLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = DxeServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeServicesTableLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + UefiLib + DebugLib + + +[Guids] + gEfiDxeServicesTableGuid ## CONSUMES ## SystemTable + diff --git a/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni new file mode 100644 index 000000000..527c19b0b --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of DXE Services Table Library using EFI Configuration Table. +// +// DXE Services Table Library that retrieves a pointer to the DXE Services +// Table from the Configuration Table in the EFI System Table. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Uses EFI Configuration Table" + +#string STR_MODULE_DESCRIPTION #language en-US "DXE Services Table Library retrieves a pointer to the DXE Services Table from the Configuration Table in the EFI System Table." + diff --git a/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c new file mode 100644 index 000000000..d9cca7eb5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c @@ -0,0 +1,98 @@ +/** @file +Implementation of SmBusLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + + +#include "InternalSmbusLib.h" + + +// +// Global variable to cache pointer to Smbus protocol. +// +EFI_SMBUS_HC_PROTOCOL *mSmbus = NULL; + +/** + The constructor function caches the pointer to Smbus protocol. + + The constructor function locates Smbus protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmbusLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiSmbusHcProtocolGuid, NULL, (VOID**) &mSmbus); + ASSERT_EFI_ERROR (Status); + ASSERT (mSmbus != NULL); + + return Status; +} + +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance + that it will use to execute the SMBus transactions. + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. + The maximum number of bytes can be revision specific + and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave + device. Not all operations require this argument. The + length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + RETURN_STATUS ReturnStatus; + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + + ReturnStatus = mSmbus->Execute ( + mSmbus, + SmbusDeviceAddress, + SMBUS_LIB_COMMAND (SmBusAddress), + SmbusOperation, + SMBUS_LIB_PEC (SmBusAddress), + &Length, + Buffer + ); + if (Status != NULL) { + *Status = ReturnStatus; + } + + return Length; +} diff --git a/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf new file mode 100644 index 000000000..237a839fb --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf @@ -0,0 +1,46 @@ +## @file +# SMBUS Library that layers on top of the SMBUS Protocol. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeSmbusLib + MODULE_UNI_FILE = DxeSmbusLib.uni + FILE_GUID = 4F369FB1-31A7-423c-960E-B3EFD337894F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmbusLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = SmbusLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SmbusLib.c + DxeSmbusLib.c + InternalSmbusLib.h + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + UefiBootServicesTableLib + DebugLib + + +[Protocols] + gEfiSmbusHcProtocolGuid ## CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiSmbusHcProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni new file mode 100644 index 000000000..390636f75 --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni @@ -0,0 +1,16 @@ +// /** @file +// SMBUS Library that layers on top of the SMBUS Protocol. +// +// SMBUS Library that layers on top of the SMBUS Protocol. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMBUS Library that layers on top of the SMBUS Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "SMBUS Library that layers on top of the SMBUS Protocol." + diff --git a/roms/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h b/roms/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h new file mode 100644 index 000000000..dac6c4ceb --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h @@ -0,0 +1,79 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#ifndef __INTERNAL_SMBUS_LIB_H_ +#define __INTERNAL_SMBUS_LIB_H_ + + +#include + +#include + +#include +#include +#include +#include + +#include + +// +// Declaration for internal functions +// +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance + that it will use toexecute the SMBus transactions. + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will + do. The maximum number of bytes can be revision specific + and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave + device. Not all operations require this argument. The + length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + The constructor function caches the pointer to Smbus protocol. + + The constructor function locates Smbus protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmbusLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c b/roms/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c new file mode 100644 index 000000000..e16d3491f --- /dev/null +++ b/roms/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c @@ -0,0 +1,586 @@ +/** @file +Implementation of SmBusLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "InternalSmbusLib.h" + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not + completed because a failure reflected in the Host Status + Register bit. Device errors are a result of a transaction + collision, illegal command field, unclaimed cycle (host + initiated), or bus errors (collisions). + RETURN_UNSUPPORTED: The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickRead, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_UNSUPPORTED: The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickWrite, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle(host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReceiveByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle(host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusSendByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failurereflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusWriteByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is + incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadWord, SmBusAddress, 2, &Word, Status); + + return Word; +} + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the SMBUS + command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. + (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Word = Value; + InternalSmBusExec (EfiSmbusWriteWord, SmBusAddress, 2, &Word, Status); + + return Value; +} + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is + incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusProcessCall, SmBusAddress, 2, &Value, Status); + + return Value; +} + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer The pointer to the buffer to store the bytes read from + the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the SMBUS + command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is + incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 0x20, Buffer, Status); +} + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + MBUS Command, SMBUS Data Length, and PEC. + @param Buffer The pointer to the buffer to store the bytes read from + the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is + incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Length = SMBUS_LIB_LENGTH (SmBusAddress); + return InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, Length, Buffer, Status); +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer The pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer The pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is + incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + ASSERT (WriteBuffer != NULL); + ASSERT (ReadBuffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Length = SMBUS_LIB_LENGTH (SmBusAddress); + // + // Assuming that ReadBuffer is large enough to save another memory copy. + // + ReadBuffer = CopyMem (ReadBuffer, WriteBuffer, Length); + return InternalSmBusExec (EfiSmbusBWBRProcessCall, SmBusAddress, Length, ReadBuffer, Status); +} diff --git a/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c new file mode 100644 index 000000000..27f9d526e --- /dev/null +++ b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c @@ -0,0 +1,57 @@ +/** @file + MM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +EFI_MM_SYSTEM_TABLE *gMmst = NULL; + +/** + The constructor function caches the pointer of the MM Services Table. + + @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 +MmServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_MM_BASE_PROTOCOL *InternalMmBase; + + InternalMmBase = NULL; + // + // Retrieve MM Base Protocol, Do not use gBS from UefiBootServicesTableLib on purpose + // to prevent inclusion of gBS, gST, and gImageHandle from SMM Drivers unless the + // MM driver explicity declares that dependency. + // + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiMmBaseProtocolGuid, + NULL, + (VOID **)&InternalMmBase + ); + ASSERT_EFI_ERROR (Status); + ASSERT (InternalMmBase != NULL); + + // + // We are in MM, retrieve the pointer to MM System Table + // + InternalMmBase->GetMmstLocation (InternalMmBase, &gMmst); + ASSERT (gMmst != NULL); + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf new file mode 100644 index 000000000..2cd5145a5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf @@ -0,0 +1,40 @@ +## @file +# MM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = MmServicesTableLib + MODULE_UNI_FILE = MmServicesTableLib.uni + FILE_GUID = 9508ECFD-66D1-4B4C-9415-F25F0FFF9E93 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = MmServicesTableLib|DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION = 0x00010032 + CONSTRUCTOR = MmServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + MmServicesTableLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + +[Protocols] + gEfiMmBaseProtocolGuid ## CONSUMES + +[Depex] + gEfiMmBaseProtocolGuid diff --git a/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni new file mode 100644 index 000000000..ff52aa564 --- /dev/null +++ b/roms/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni @@ -0,0 +1,18 @@ +// /** @file +// +// MM Services Table Library. +// +// It implements MmServicesTableLib based on gEfiMmBaseProtocolGuid, which +// is simply gEfiSmmBase2ProtocolGuid under the hood. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "MM Services Table Library" + +#string STR_MODULE_DESCRIPTION #language en-US "MM Services Table Library." diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c new file mode 100644 index 000000000..b0d51c45b --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c @@ -0,0 +1,64 @@ +/** @file + Instance of Base PCI Segment Library that support multi-segment PCI configuration access. + + PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to + support multi-segment PCI configuration access through enhanced configuration access mechanism. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciSegmentLibCommon.h" + +/** + Return the virtual address for the physical address. + + @param Address The physical address. + + @retval The virtual address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ) +{ + return Address; +} + +/** + Register a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + // + // Use PciSegmentLibGetEcamAddress() to validate the Address. + // + DEBUG_CODE ( + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count); + ); + return RETURN_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf new file mode 100644 index 000000000..dbf59ad7d --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf @@ -0,0 +1,41 @@ +## @file +# Instance of Base PCI Segment Library that support multi-segment PCI configuration access. +# +# PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to +# support multi-segment PCI configuration access through enhanced configuration access mechanism. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciSegmentLibSegmentInfo + MODULE_UNI_FILE = BasePciSegmentLibSegmentInfo.uni + FILE_GUID = 3427D883-E093-4CC9-BE85-6BD4058E96E2 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentLibCommon.h + PciSegmentLibCommon.c + BasePciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + DebugLib + PciSegmentInfoLib diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni new file mode 100644 index 000000000..9b17cc9fd --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Base PCI Segment Library that support multi-segment PCI configuration access. + +// PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to +// support multi-segment PCI configuration access through enhanced configuration access mechanism. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base PCI Segment Library that support multi-segment PCI configuration access." + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to support multi-segment PCI configuration access through enhanced configuration access mechanism." diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c new file mode 100644 index 000000000..75931d46e --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c @@ -0,0 +1,313 @@ +/** @file + Instance of Runtime PCI Segment Library that support multi-segment PCI configuration access. + + PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to + support multi-segment PCI configuration access through enhanced configuration access mechanism. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciSegmentLibCommon.h" +#include +#include +#include +#include +#include +#include +#include + +/// +/// Define table for mapping PCI Segment MMIO physical addresses to virtual addresses at OS runtime +/// +typedef struct { + UINTN PhysicalAddress; + UINTN VirtualAddress; +} PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE; + +/// +/// Set Virtual Address Map Event +/// +EFI_EVENT mDxeRuntimePciSegmentLibVirtualNotifyEvent = NULL; + +/// +/// The number of PCI devices that have been registered for runtime access. +/// +UINTN mDxeRuntimePciSegmentLibNumberOfRuntimeRanges = 0; + +/// +/// The table of PCI devices that have been registered for runtime access. +/// +PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE *mDxeRuntimePciSegmentLibRegistrationTable = NULL; + +/// +/// The table index of the most recent virtual address lookup. +/// +UINTN mDxeRuntimePciSegmentLibLastRuntimeRange = 0; + +/** + Convert the physical PCI Express MMIO addresses for all registered PCI devices + to virtual addresses. + + @param[in] Event The event that is being processed. + @param[in] Context The Event Context. +**/ +VOID +EFIAPI +DxeRuntimePciSegmentLibVirtualNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + EFI_STATUS Status; + + // + // If there have been no runtime registrations, then just return + // + if (mDxeRuntimePciSegmentLibRegistrationTable == NULL) { + return; + } + + // + // Convert physical addresses associated with the set of registered PCI devices to + // virtual addresses. + // + for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) { + Status = EfiConvertPointer (0, (VOID **) &(mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress)); + ASSERT_EFI_ERROR (Status); + } + + // + // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address. + // + Status = EfiConvertPointer (0, (VOID **) &mDxeRuntimePciSegmentLibRegistrationTable); + ASSERT_EFI_ERROR (Status); +} + +/** + The constructor function caches the PCI Express Base Address and creates a + Set Virtual Address Map event to convert physical address to virtual addresses. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor completed successfully. + @retval Other value The constructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciSegmentLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + TPL_NOTIFY, + DxeRuntimePciSegmentLibVirtualNotify, + NULL, + &mDxeRuntimePciSegmentLibVirtualNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + The destructor function frees any allocated buffers and closes the Set Virtual + Address Map event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeRuntimePciSegmentLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // If one or more PCI devices have been registered for runtime access, then + // free the registration table. + // + if (mDxeRuntimePciSegmentLibRegistrationTable != NULL) { + FreePool (mDxeRuntimePciSegmentLibRegistrationTable); + } + + // + // Close the Set Virtual Address Map event + // + Status = gBS->CloseEvent (mDxeRuntimePciSegmentLibVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Register a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + RETURN_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Index; + VOID *NewTable; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINT64 EcamAddress; + + // + // Convert Address to a ECAM address at the beginning of the PCI Configuration + // header for the specified PCI Bus/Dev/Func + // + Address &= ~(UINTN)EFI_PAGE_MASK; + SegmentInfo = GetPciSegmentInfo (&Count); + EcamAddress = PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count); + + // + // Return an error if this function is called after ExitBootServices(). + // + if (EfiAtRuntime ()) { + return RETURN_UNSUPPORTED; + } + if (sizeof (UINTN) == sizeof (UINT32)) { + ASSERT (EcamAddress < BASE_4GB); + } + Address = (UINTN)EcamAddress; + + // + // See if Address has already been registered for runtime access + // + for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) { + if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == Address) { + return RETURN_SUCCESS; + } + } + + // + // Get the GCD Memory Descriptor for the ECAM Address + // + Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS + // will allocate a virtual address range for the 4KB PCI Configuration Header. + // + Status = gDS->SetMemorySpaceAttributes (Address, EFI_PAGE_SIZE, Descriptor.Attributes | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + // + // Grow the size of the registration table + // + NewTable = ReallocateRuntimePool ( + (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 0) * sizeof (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE), + (mDxeRuntimePciSegmentLibNumberOfRuntimeRanges + 1) * sizeof (PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE), + mDxeRuntimePciSegmentLibRegistrationTable + ); + if (NewTable == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + mDxeRuntimePciSegmentLibRegistrationTable = NewTable; + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumberOfRuntimeRanges].PhysicalAddress = Address; + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibNumberOfRuntimeRanges].VirtualAddress = Address; + mDxeRuntimePciSegmentLibNumberOfRuntimeRanges++; + + return RETURN_SUCCESS; +} + +/** + Return the linear address for the physical address. + + @param Address The physical address. + + @retval The linear address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ) +{ + UINTN Index; + // + // If SetVirtualAddressMap() has not been called, then just return the physical address + // + if (!EfiGoneVirtual ()) { + return Address; + } + + // + // See if there is a physical address match at the exact same index as the last address match + // + if (mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) { + // + // Convert the physical address to a virtual address and return the virtual address + // + return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].VirtualAddress; + } + + // + // Search the entire table for a physical address match + // + for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) { + if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) { + // + // Cache the matching index value + // + mDxeRuntimePciSegmentLibLastRuntimeRange = Index; + // + // Convert the physical address to a virtual address and return the virtual address + // + return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress; + } + } + + // + // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint. + // + ASSERT (FALSE); + CpuBreakpoint (); + + // + // Return the physical address + // + return Address; +} diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf new file mode 100644 index 000000000..ae9f11b69 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf @@ -0,0 +1,47 @@ +## @file +# Instance of Runtime PCI Segment Library that support multi-segment PCI configuration access. +# +# PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to +# support multi-segment PCI configuration access through enhanced configuration access mechanism. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeRuntimePciSegmentLibSegmentInfo + MODULE_UNI_FILE = DxeRuntimePciSegmentLibSegmentInfo.uni + FILE_GUID = F73EB3DE-F4E3-47CB-9F18-97796AE06314 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib|DXE_RUNTIME_DRIVER + CONSTRUCTOR = DxeRuntimePciSegmentLibConstructor + DESTRUCTOR = DxeRuntimePciSegmentLibDestructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentLibCommon.h + PciSegmentLibCommon.c + DxeRuntimePciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + DebugLib + PciSegmentInfoLib + UefiRuntimeLib + MemoryAllocationLib + DxeServicesTableLib + UefiBootServicesTableLib diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni new file mode 100644 index 000000000..112134328 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Runtime PCI Segment Library that support multi-segment PCI configuration access. + +// PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to +// support multi-segment PCI configuration access through enhanced configuration access mechanism. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Runtime PCI Segment Library that support multi-segment PCI configuration access." + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Library that consumes segment information provided by PciSegmentInfoLib to support multi-segment PCI configuration access through enhanced configuration access mechanism." diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c new file mode 100644 index 000000000..a76e9d9ad --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c @@ -0,0 +1,1368 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciSegmentLibCommon.h" + +typedef struct { + UINT32 Register : 12; + UINT32 Function : 3; + UINT32 Device : 5; + UINT32 Bus : 8; + UINT32 Reserved1 : 4; + UINT32 Segment : 16; + UINT32 Reserved2 : 16; +} PCI_SEGMENT_LIB_ADDRESS_STRUCTURE; + +/** + Internal function that converts PciSegmentLib format address that encodes the PCI Bus, Device, + Function and Register to ECAM (Enhanced Configuration Access Mechanism) address. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param SegmentInfo An array of PCI_SEGMENT_INFO holding the segment information. + @param Count Number of segments. + + @retval ECAM address. +**/ +UINTN +PciSegmentLibGetEcamAddress ( + IN UINT64 Address, + IN CONST PCI_SEGMENT_INFO *SegmentInfo, + IN UINTN Count + ) +{ + while (Count != 0) { + if (SegmentInfo->SegmentNumber == ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Segment) { + break; + } + SegmentInfo++; + Count--; + } + ASSERT (Count != 0); + ASSERT ( + (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved1 == 0) && + (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Reserved2 == 0) + ); + ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus >= SegmentInfo->StartBusNumber); + ASSERT (((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus <= SegmentInfo->EndBusNumber); + + Address = SegmentInfo->BaseAddress + PCI_ECAM_ADDRESS ( + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Bus, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Device, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Function, + ((PCI_SEGMENT_LIB_ADDRESS_STRUCTURE *)&Address)->Register); + + if (sizeof (UINTN) == sizeof (UINT32)) { + ASSERT (Address < BASE_4GB); + } + + return PciSegmentLibVirtualAddress ((UINTN)Address); +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioRead8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioWrite8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAnd8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAndThenOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldRead8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldWrite8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAnd8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr8 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioRead16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioWrite16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAnd16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAndThenOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldRead16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldWrite16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAnd16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr16 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioRead32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count)); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioWrite32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAnd32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioAndThenOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldRead32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldWrite32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + + Reads the 32-bit PCI configuration register specified by Address, performs a bitwise + AND between the read result and the value specified by AndData, and writes the result + to the 32-bit PCI configuration register specified by Address. The value written to + the PCI configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAnd32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + SegmentInfo = GetPciSegmentInfo (&Count); + return MmioBitFieldAndThenOr32 (PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count), StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINTN Address; + + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + SegmentInfo = GetPciSegmentInfo (&Count); + Address = PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo, Count); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((Address & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = MmioRead8 (Address); + Address += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (Address & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, MmioRead16 (Address)); + Address += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, MmioRead32 (Address)); + Address += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, MmioRead16 (Address)); + Address += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = MmioRead8 (Address); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAddress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + UINTN Count; + PCI_SEGMENT_INFO *SegmentInfo; + UINTN Address; + + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + SegmentInfo = GetPciSegmentInfo (&Count); + Address = PciSegmentLibGetEcamAddress (StartAddress, SegmentInfo, Count); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((Address & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + MmioWrite8 (Address, *(UINT8*)Buffer); + Address += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (Address & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + MmioWrite16 (Address, ReadUnaligned16 (Buffer)); + Address += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + MmioWrite32 (Address, ReadUnaligned32 (Buffer)); + Address += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + MmioWrite16 (Address, ReadUnaligned16 (Buffer)); + Address += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + MmioWrite8 (Address, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h new file mode 100644 index 000000000..466837281 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h @@ -0,0 +1,51 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI_SEGMENT_LIB_COMMON_H_ +#define _PCI_SEGMENT_LIB_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +/** + Return the linear address for the physical address. + + @param Address The physical address. + + @retval The linear address. +**/ +UINTN +PciSegmentLibVirtualAddress ( + IN UINTN Address + ); + +/** + Internal function that converts PciSegmentLib format address that encodes the PCI Bus, Device, + Function and Register to ECAM (Enhanced Configuration Access Mechanism) address. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param SegmentInfo An array of PCI_SEGMENT_INFO holding the segment information. + @param Count Number of segments. + + @retval ECAM address. +**/ +UINTN +PciSegmentLibGetEcamAddress ( + IN UINT64 Address, + IN CONST PCI_SEGMENT_INFO *SegmentInfo, + IN UINTN Count + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c new file mode 100644 index 000000000..85dee7f52 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c @@ -0,0 +1,95 @@ +/** @file + Entry point to a the PEI Core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +// +// The Library classes this module produced +// +#include +#include +#include + +/** + The entry point of PE/COFF Image for the PEI Core. + + This function is the entry point for the PEI Foundation, which allows the SEC phase + to pass information about the stack, temporary RAM and the Boot Firmware Volume. + In addition, it also allows the SEC phase to pass services and data forward for use + during the PEI phase in the form of one or more PPIs. + There is no limit to the number of additional PPIs that can be passed from SEC into + the PEI Foundation. As part of its initialization phase, the PEI Foundation will add + these SEC-hosted PPIs to its PPI database such that both the PEI Foundation and any + modules can leverage the associated service calls and/or code in these early PPIs. + This function is required to call ProcessModuleEntryPointList() with the Context + parameter set to NULL. ProcessModuleEntryPoint() is never expected to return. + The PEI Core is responsible for calling ProcessLibraryConstructorList() as soon as + the PEI Services Table and the file handle for the PEI Core itself have been established. + If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system. + + @param SecCoreData Points to a data structure containing information about the + PEI core's operating environment, such as the size and + location of temporary RAM, the stack location and the BFV + location. + + @param PpiList Points to a list of one or more PPI descriptors to be + installed initially by the PEI core. An empty PPI list + consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. + As part of its initialization phase, the PEI Foundation will + add these SEC-hosted PPIs to its PPI database, such that both + the PEI Foundation and any modules can leverage the associated + service calls and/or code in these early PPIs. + +**/ +VOID +EFIAPI +_ModuleEntryPoint( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList +) +{ + ProcessModuleEntryPointList (SecCoreData, PpiList, NULL); + + // + // Should never return + // + ASSERT(FALSE); + CpuDeadLoop (); +} + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + This function is required to call _ModuleEntryPoint() passing in SecCoreData and PpiList. + + @param SecCoreData Points to a data structure containing information about the PEI core's + operating environment, such as the size and location of temporary RAM, + the stack location and the BFV location. + + @param PpiList Points to a list of one or more PPI descriptors to be installed + initially by the PEI core. An empty PPI list consists of + a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. + As part of its initialization phase, the PEI Foundation will + add these SEC-hosted PPIs to its PPI database, such that both + the PEI Foundationand any modules can leverage the associated + service calls and/or code in these early PPIs. + +**/ +VOID +EFIAPI +EfiMain ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + _ModuleEntryPoint (SecCoreData, PpiList); +} diff --git a/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf new file mode 100644 index 000000000..c14a84dd3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf @@ -0,0 +1,34 @@ +## @file +# Module entry point library for PEI core. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiCoreEntryPoint + MODULE_UNI_FILE = PeiCoreEntryPoint.uni + FILE_GUID = b3b0654a-969d-4096-86cb-27e262a02083 + MODULE_TYPE = PEI_CORE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiCoreEntryPoint|PEI_CORE + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiCoreEntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + diff --git a/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni new file mode 100644 index 000000000..f4c12c0e6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni @@ -0,0 +1,16 @@ +// /** @file +// Module entry point library for PEI core. +// +// Module entry point library for PEI core. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for PEI core" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for PEI core." + diff --git a/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf new file mode 100644 index 000000000..4f03e4178 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf @@ -0,0 +1,40 @@ +## @file +# Instance of Post Code Library based on Report Status Code Library. +# +# Post Code Library that layers on top of a Report Status Code Library instance. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiDxePostCodeLibReportStatusCode + MODULE_UNI_FILE = PeiDxePostCodeLibReportStatusCode.uni + FILE_GUID = e062c52d-78dc-4cc5-b246-b13497a8123c + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PostCodeLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER PEIM PEI_CORE UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PostCode.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + PcdLib + ReportStatusCodeLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni new file mode 100644 index 000000000..92d0cdaa4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Post Code Library based on Report Status Code Library. +// +// Post Code Library that layers on top of a Report Status Code Library instance. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Post Code Library based on Report Status Code Library" + +#string STR_MODULE_DESCRIPTION #language en-US "The Post Code Library that layers on top of a Report Status Code Library instance." + diff --git a/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c new file mode 100644 index 000000000..cccb70673 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c @@ -0,0 +1,153 @@ +/** @file + Post code library instace bases on report status code library + PostCode Library for PEIMs and DXE drivers that send PostCode to ReportStatusCode + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +/** + Converts POST code value to status code value. + + This macro converts the post code to status code value. Bits 0..4 of PostCode + are mapped to bits 16..20 of status code value, and bits 5..7 of PostCode are mapped to bits + 24..26 of status code value. + + @param PostCode POST code value. + + @return The converted status code value. + +**/ +#define POST_CODE_TO_STATUS_CODE_VALUE(PostCode) \ + ((EFI_STATUS_CODE_VALUE) (((PostCode & 0x1f) << 16) | ((PostCode & 0x3) << 19))) + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Post Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, POST_CODE_TO_STATUS_CODE_VALUE (Value)); + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Post + Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description The pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return The 32-bit value to write to the POST card. + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + if (Description == NULL) { + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + POST_CODE_TO_STATUS_CODE_VALUE (Value) + ); + } else { + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + POST_CODE_TO_STATUS_CODE_VALUE (Value), + Description, + AsciiStrSize (Description) + ); + } + + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED + bit of PcdPostCodePropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is set. + @retval FALSE The POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED bit of + PcdPostCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +PostCodeDescriptionEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdPostCodePropertyMask) & POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} + diff --git a/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c new file mode 100644 index 000000000..9feb35056 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c @@ -0,0 +1,513 @@ +/** @file + Provide generic extract guided section functions for PEI phase. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +#define PEI_EXTRACT_HANDLER_INFO_SIGNATURE SIGNATURE_32 ('P', 'E', 'H', 'I') + +typedef struct { + UINT32 Signature; + UINT32 NumberOfExtractHandler; + GUID *ExtractHandlerGuidTable; + EXTRACT_GUIDED_SECTION_DECODE_HANDLER *ExtractDecodeHandlerTable; + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable; +} PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO; + +/** + Build guid hob for the global memory to store the registered guid and Handler list. + If GuidHob exists, HandlerInfo will be directly got from Guid hob data. + + @param[in, out] InfoPointer The pointer to pei handler information structure. + + @retval RETURN_SUCCESS Build Guid hob for the global memory space to store guid and function tables. + @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated. +**/ +RETURN_STATUS +PeiGetExtractGuidedSectionHandlerInfo ( + IN OUT PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO **InfoPointer + ) +{ + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + EFI_PEI_HOB_POINTERS Hob; + + // + // First try to get handler information from guid hob specified by CallerId. + // + Hob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GetHobList ()); + while (Hob.Raw != NULL) { + if (CompareGuid (&(Hob.Guid->Name), &gEfiCallerIdGuid)) { + HandlerInfo = (PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *) GET_GUID_HOB_DATA (Hob.Guid); + if (HandlerInfo->Signature == PEI_EXTRACT_HANDLER_INFO_SIGNATURE) { + // + // Update Table Pointer when hob start address is changed. + // + if (HandlerInfo->ExtractHandlerGuidTable != (GUID *) (HandlerInfo + 1)) { + HandlerInfo->ExtractHandlerGuidTable = (GUID *) (HandlerInfo + 1); + HandlerInfo->ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractHandlerGuidTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID) + ); + HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * + sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + ); + } + // + // Return HandlerInfo pointer. + // + *InfoPointer = HandlerInfo; + return EFI_SUCCESS; + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, Hob.Raw); + } + + // + // If Guid Hob is not found, Build CallerId Guid hob to store Handler Info + // + HandlerInfo = BuildGuidHob ( + &gEfiCallerIdGuid, + sizeof (PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO) + + PcdGet32 (PcdMaximumGuidedExtractHandler) * + (sizeof (GUID) + sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER)) + ); + if (HandlerInfo == NULL) { + // + // No enough resource to build guid hob. + // + *InfoPointer = NULL; + return EFI_OUT_OF_RESOURCES; + } + // + // Init HandlerInfo structure + // + HandlerInfo->Signature = PEI_EXTRACT_HANDLER_INFO_SIGNATURE; + HandlerInfo->NumberOfExtractHandler = 0; + HandlerInfo->ExtractHandlerGuidTable = (GUID *) (HandlerInfo + 1); + HandlerInfo->ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractHandlerGuidTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID) + ); + HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) ( + (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable + + PcdGet32 (PcdMaximumGuidedExtractHandler) * + sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + ); + // + // return the created HandlerInfo. + // + *InfoPointer = HandlerInfo; + return EFI_SUCCESS; +} + +/** + Retrieve the list GUIDs that have been registered through ExtractGuidedSectionRegisterHandlers(). + + Sets ExtractHandlerGuidTable so it points at a callee allocated array of registered GUIDs. + The total number of GUIDs in the array are returned. Since the array of GUIDs is callee allocated + and caller must treat this array of GUIDs as read-only data. + If ExtractHandlerGuidTable is NULL, then ASSERT(). + + @param[out] ExtractHandlerGuidTable A pointer to the array of GUIDs that have been registered through + ExtractGuidedSectionRegisterHandlers(). + + @return the number of the supported extract guided Handler. + +**/ +UINTN +EFIAPI +ExtractGuidedSectionGetGuidList ( + OUT GUID **ExtractHandlerGuidTable + ) +{ + EFI_STATUS Status; + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + ASSERT (ExtractHandlerGuidTable != NULL); + + // + // Get all registered handler information + // + Status = PeiGetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (EFI_ERROR (Status)) { + *ExtractHandlerGuidTable = NULL; + return 0; + } + + // + // Get GuidTable and Table Number + // + ASSERT (HandlerInfo != NULL); + *ExtractHandlerGuidTable = HandlerInfo->ExtractHandlerGuidTable; + return HandlerInfo->NumberOfExtractHandler; +} + +/** + Registers handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and EXTRACT_GUIDED_SECTION_DECODE_HANDLER + for a specific GUID section type. + + Registers the handlers specified by GetInfoHandler and DecodeHandler with the GUID specified by SectionGuid. + If the GUID value specified by SectionGuid has already been registered, then return RETURN_ALREADY_STARTED. + If there are not enough resources available to register the handlers then RETURN_OUT_OF_RESOURCES is returned. + + If SectionGuid is NULL, then ASSERT(). + If GetInfoHandler is NULL, then ASSERT(). + If DecodeHandler is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the the handlers + of the GUIDed section type being registered. + @param[in] GetInfoHandler The pointer to a function that 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. + @param[in] DecodeHandler The pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to register the handlers. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionRegisterHandlers ( + IN CONST GUID *SectionGuid, + IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler, + IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler + ) +{ + EFI_STATUS Status; + UINT32 Index; + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + // + // Check input parameter + // + ASSERT (SectionGuid != NULL); + ASSERT (GetInfoHandler != NULL); + ASSERT (DecodeHandler != NULL); + + + + // + // Get the registered handler information + // + Status = PeiGetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) { + // + // If the guided handler has been registered before, only update its handler. + // + HandlerInfo->ExtractDecodeHandlerTable [Index] = DecodeHandler; + HandlerInfo->ExtractGetInfoHandlerTable [Index] = GetInfoHandler; + return RETURN_SUCCESS; + } + } + + // + // Check the global table is enough to contain new Handler. + // + if (HandlerInfo->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) { + return RETURN_OUT_OF_RESOURCES; + } + + // + // Register new Handler and guid value. + // + CopyGuid (HandlerInfo->ExtractHandlerGuidTable + HandlerInfo->NumberOfExtractHandler, SectionGuid); + HandlerInfo->ExtractDecodeHandlerTable [HandlerInfo->NumberOfExtractHandler] = DecodeHandler; + HandlerInfo->ExtractGetInfoHandlerTable [HandlerInfo->NumberOfExtractHandler++] = GetInfoHandler; + + // + // Build the Guided Section GUID HOB to record the GUID itself. + // Then the content of the GUIDed HOB will be the same as the GUID value itself. + // + BuildGuidDataHob ( + (EFI_GUID *) SectionGuid, + (VOID *) SectionGuid, + sizeof (GUID) + ); + + return RETURN_SUCCESS; +} + +/** + Retrieves a GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to retrieve and return 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 any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler + of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to retrieve the OututBufferSize, ScratchSize, and Attributes values. The return status from the handler of + type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER is returned. + + 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 Get the required information successfully. + @retval RETURN_UNSUPPORTED The GUID from the section specified by InputSection does not match any of + the GUIDs registered with ExtractGuidedSectionRegisterHandlers(). + @retval Others The return status from the handler associated with the GUID retrieved from + the section specified by InputSection. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetInfo ( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ) +{ + UINT32 Index; + EFI_STATUS Status; + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + EFI_GUID *SectionDefinitionGuid; + + // + // Check input parameter + // + ASSERT (InputSection != NULL); + ASSERT (OutputBufferSize != NULL); + ASSERT (ScratchBufferSize != NULL); + ASSERT (SectionAttribute != NULL); + + // + // Get all registered handler information. + // + Status = PeiGetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) { + // + // Call the match handler to get information for the input section data. + // + return HandlerInfo->ExtractGetInfoHandlerTable [Index] ( + InputSection, + OutputBufferSize, + ScratchBufferSize, + SectionAttribute + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves the GUID from a GUIDed section and uses that GUID to select an associated handler of type + EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers(). + The selected handler is used to decode the data in a GUIDed section and return the result in a caller + allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(), + then RETURN_UNSUPPORTED is returned. + If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler + of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers() + is used to decode InputSection 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. This function is responsible for computing the EFI_AUTH_STATUS_PLATFORM_OVERRIDE + bit of in AuthenticationStatus. The return status from the handler of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER is returned. + + 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. + + @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 +ExtractGuidedSectionDecode ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + IN VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ) +{ + UINT32 Index; + EFI_STATUS Status; + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + EFI_GUID *SectionDefinitionGuid; + + // + // Check input parameter + // + ASSERT (InputSection != NULL); + ASSERT (OutputBuffer != NULL); + ASSERT (AuthenticationStatus != NULL); + + // + // Get all registered handler information. + // + Status = PeiGetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + if (IS_SECTION2 (InputSection)) { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid); + } else { + SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid); + } + + // + // Search the match registered Extract handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) { + // + // Call the match handler to extract raw data for the input guided section. + // + return HandlerInfo->ExtractDecodeHandlerTable [Index] ( + InputSection, + OutputBuffer, + ScratchBuffer, + AuthenticationStatus + ); + } + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + +/** + Retrieves handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and + EXTRACT_GUIDED_SECTION_DECODE_HANDLER for a specific GUID section type. + + Retrieves the handlers associated with SectionGuid and returns them in + GetInfoHandler and DecodeHandler. + + If the GUID value specified by SectionGuid has not been registered, then + return RETURN_NOT_FOUND. + + If SectionGuid is NULL, then ASSERT(). + + @param[in] SectionGuid A pointer to the GUID associated with the handlersof the GUIDed + section type being retrieved. + @param[out] GetInfoHandler Pointer to a function that 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. + This is an optional parameter that may be NULL. If it is NULL, then + the previously registered handler is not returned. + @param[out] DecodeHandler Pointer to a function that decodes a GUIDed section into a caller + allocated output buffer. This is an optional parameter that may be NULL. + If it is NULL, then the previously registered handler is not returned. + + @retval RETURN_SUCCESS The handlers were retrieved. + @retval RETURN_NOT_FOUND No handlers have been registered with the specified GUID. + +**/ +RETURN_STATUS +EFIAPI +ExtractGuidedSectionGetHandlers ( + IN CONST GUID *SectionGuid, + OUT EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *GetInfoHandler, OPTIONAL + OUT EXTRACT_GUIDED_SECTION_DECODE_HANDLER *DecodeHandler OPTIONAL + ) +{ + EFI_STATUS Status; + UINT32 Index; + PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; + + // + // Check input parameter + // + ASSERT (SectionGuid != NULL); + + // + // Get the registered handler information + // + Status = PeiGetExtractGuidedSectionHandlerInfo (&HandlerInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Search the match registered GetInfo handler for the input guided section. + // + ASSERT (HandlerInfo != NULL); + for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) { + if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) { + + // + // If the guided handler has been registered before, then return the registered handlers. + // + if (GetInfoHandler != NULL) { + *GetInfoHandler = HandlerInfo->ExtractGetInfoHandlerTable[Index]; + } + if (DecodeHandler != NULL) { + *DecodeHandler = HandlerInfo->ExtractDecodeHandlerTable[Index]; + } + return RETURN_SUCCESS; + } + } + return RETURN_NOT_FOUND; +} diff --git a/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf new file mode 100644 index 000000000..5cbc34fc0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf @@ -0,0 +1,43 @@ +## @file +# Instance of ExtractGuidedSection Library for PEI phase. +# +# This library provides generic extract guided section functions for PEIM and PEI_CORE module. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiExtractGuidedSectionLib + MODULE_UNI_FILE = PeiExtractGuidedSectionLib.uni + FILE_GUID = 41ddf016-2a11-415f-8880-00d938e9541a + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = ExtractGuidedSectionLib|PEIM PEI_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiExtractGuidedSectionLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + DebugLib + HobLib + PcdLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni new file mode 100644 index 000000000..fa4f11e6b --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of ExtractGuidedSection Library for PEI phase. +// +// This library provides generic extract guided section functions for PEIM and PEI_CORE module. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Extract Guided Section Library" + +#string STR_MODULE_DESCRIPTION #language en-US "This library provides generic extract guided section functions for PEIM and PEI_CORE modules." + diff --git a/roms/edk2/MdePkg/Library/PeiHobLib/HobLib.c b/roms/edk2/MdePkg/Library/PeiHobLib/HobLib.c new file mode 100644 index 000000000..ed40b6806 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiHobLib/HobLib.c @@ -0,0 +1,852 @@ +/** @file + Provide Hob Library functions for Pei phase. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer + to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through + the EFI System Table by looking up theHOB list GUID in the System Configuration Table. + Since the System Configuration Table does not exist that the time the DXE Core is + launched, the DXE Core uses a global variable from the DXE Core Entry Point Library + to manage the pointer to the HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + EFI_STATUS Status; + VOID *HobList; + + Status = PeiServicesGetHobList (&HobList); + ASSERT_EFI_ERROR (Status); + ASSERT (HobList != NULL); + + return HobList; +} + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + Returns the next instance of the matched GUID HOB from the starting HOB. + + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + Returns the first instance of the matched GUID HOB among the whole HOB list. + + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + + If the pointer to the HOB list is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + Get the system boot mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param VOID. + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootModeHob ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + return BootMode; +} + +/** + Adds a new HOB to the HOB List. + + This internal function enables PEIMs to create various types of HOBs. + + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + + @retval NULL The HOB could not be allocated. + @retval others The address of new HOB. + +**/ +VOID * +EFIAPI +InternalPeiCreateHob ( + IN UINT16 Type, + IN UINT16 Length + ) +{ + EFI_STATUS Status; + VOID *Hob; + + Status = PeiServicesCreateHob (Type, Length, &Hob); + if (EFI_ERROR (Status)) { + Hob = NULL; + } + // + // Assume the process of HOB building is always successful. + // + ASSERT (Hob != NULL); + return Hob; +} + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + +/** + Builds a HOB that describes a chunk of system memory with Owner GUID. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + @param OwnerGUID GUID for the owner of this resource. + +**/ +VOID +EFIAPI +BuildResourceDescriptorWithOwnerHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_GUID *OwnerGUID + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + if (Hob == NULL) { + return; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + + CopyGuid (&Hob->Owner, OwnerGUID); +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + if (Hob == NULL) { + return; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + ZeroMem (&(Hob->Owner), sizeof (EFI_GUID)); +} + +/** + Builds a customized HOB tagged with a GUID for identification and returns + the start address of GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure Guid is valid + // + ASSERT (Guid != NULL); + + // + // Make sure that data length is not too long. + // + ASSERT (DataLength <= (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + if (Hob == NULL) { + return Hob; + } + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + +/** + Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB + data field, and returns the start address of the GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification and copies the input + data to the HOB data field and returns the start address of the GUID HOB data. It can only be + invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + ASSERT (Data != NULL || DataLength == 0); + + HobData = BuildGuidHob (Guid, DataLength); + if (HobData == NULL) { + return HobData; + } + + return CopyMem (HobData, Data, DataLength); +} + +/** + Check FV alignment. + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + + @retval TRUE FvImage buffer is at its required alignment. + @retval FALSE FvImage buffer is not at its required alignment. + +**/ +BOOLEAN +InternalCheckFvAlignment ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT32 FvAlignment; + + FvAlignment = 0; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + + // + // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume + // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from + // its initial linked location and maintain its alignment. + // + if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) { + // + // Get FvHeader alignment + // + 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; + } + if ((UINTN)BaseAddress % FvAlignment != 0) { + // + // FvImage buffer is not at its required alignment. + // + DEBUG (( + DEBUG_ERROR, + "Unaligned FvImage found at 0x%lx:0x%lx, the required alignment is 0x%x\n", + BaseAddress, + Length, + FvAlignment + )); + return FALSE; + } + } + + return TRUE; +} + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + if (!InternalCheckFvAlignment (BaseAddress, Length)) { + ASSERT (FALSE); + return; + } + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + if (!InternalCheckFvAlignment (BaseAddress, Length)) { + ASSERT (FALSE); + return; + } + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV2, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME2)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); +} + +/** + Builds a EFI_HOB_TYPE_FV3 HOB. + + This function builds a EFI_HOB_TYPE_FV3 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param AuthenticationStatus The authentication status. + @param ExtractedFv TRUE if the FV was extracted as a file within + another firmware volume. FALSE otherwise. + @param FvName The name of the Firmware Volume. + Valid only if IsExtractedFv is TRUE. + @param FileName The name of the file. + Valid only if IsExtractedFv is TRUE. + +**/ +VOID +EFIAPI +BuildFv3Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT32 AuthenticationStatus, + IN BOOLEAN ExtractedFv, + IN CONST EFI_GUID *FvName, OPTIONAL + IN CONST EFI_GUID *FileName OPTIONAL + ) +{ + EFI_HOB_FIRMWARE_VOLUME3 *Hob; + + if (!InternalCheckFvAlignment (BaseAddress, Length)) { + ASSERT (FALSE); + return; + } + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV3, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME3)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + Hob->AuthenticationStatus = AuthenticationStatus; + Hob->ExtractedFv = ExtractedFv; + if (ExtractedFv) { + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); + } +} + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If the platform does not support Capsule Volume HOBs, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_UEFI_CAPSULE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_UEFI_CAPSULE, (UINT16) sizeof (EFI_HOB_UEFI_CAPSULE)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_CPU, (UINT16) sizeof (EFI_HOB_CPU)); + if (Hob == NULL) { + return; + } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); +} + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiBootServicesData; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType The type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_BSP_STORE)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocBspStoreGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType The type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION)); + if (Hob == NULL) { + return; + } + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} diff --git a/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf b/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf new file mode 100644 index 000000000..93284638e --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf @@ -0,0 +1,51 @@ +## @file +# Instance of HOB Library using PEI Services. +# +# HOB Library implementation that uses PEI Services to retrieve the HOB List. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiHobLib + MODULE_UNI_FILE = PeiHobLib.uni + FILE_GUID = 9643128f-ac24-4b3e-b6be-d8849a306153 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = HobLib|PEIM PEI_CORE SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + HobLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + PeiServicesLib + DebugLib + +[Guids] + gEfiHobMemoryAllocStackGuid ## SOMETIMES_PRODUCES ## HOB # MemoryAllocation StackHob + gEfiHobMemoryAllocBspStoreGuid ## SOMETIMES_PRODUCES ## HOB # MemoryAllocation BspStoreHob + gEfiHobMemoryAllocModuleGuid ## SOMETIMES_PRODUCES ## HOB # MemoryAllocation ModuleHob + +# +# [Hob] +# MEMORY_ALLOCATION ## SOMETIMES_PRODUCES +# RESOURCE_DESCRIPTOR ## SOMETIMES_PRODUCES +# FIRMWARE_VOLUME ## SOMETIMES_PRODUCES +# + diff --git a/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni b/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni new file mode 100644 index 000000000..0cc74e3aa --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of HOB Library using PEI Services. +// +// HOB Library implementation that uses PEI Services to retrieve the HOB List. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of HOB Library using PEI Services" + +#string STR_MODULE_DESCRIPTION #language en-US "HOB Library implementation that uses PEI Services to retrieve the HOB List." + diff --git a/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c new file mode 100644 index 000000000..a136c4a9a --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c @@ -0,0 +1,2350 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +/** + Reads an 8-bit I/O port, performs a bitwise OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) | OrData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) & AndData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) ((IoRead8 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) | OrData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) & AndData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) ((IoRead16 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) | OrData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) & AndData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) ((MmioRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) | OrData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) & AndData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) ((MmioRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c new file mode 100644 index 000000000..87002e428 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c @@ -0,0 +1,829 @@ +/** @file + I/O Library. The implementations are based on EFI_PEI_SERVICE->CpuIo interface. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The port is read Count times, and the read data is stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifoWorker ( + IN UINTN Port, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_STATUS Status; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + Status = CpuIo->Io.Read (PeiServices, CpuIo, Width, Port, Count, Buffer); + ASSERT_EFI_ERROR (Status); +} + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width specified by Width. + The port is written Count times, and the write data is retrieved from the provided Buffer. + + This function must guarantee that all I/O read and write operations are serialized. + If such operations are not supported, then ASSERT(). + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Count The number of times to write I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoWriteFifoWorker ( + IN UINTN Port, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINTN Count, + IN VOID *Buffer + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_STATUS Status; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + Status = CpuIo->Io.Write (PeiServices, CpuIo, Width, Port, Count, Buffer); + ASSERT_EFI_ERROR (Status); +} + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + return CpuIo->IoRead8 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + CpuIo->IoWrite8 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + return CpuIo->IoRead16 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + CpuIo->IoWrite16 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + return CpuIo->IoRead32 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + CpuIo->IoWrite32 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + return CpuIo->IoRead64 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + CpuIo->IoWrite64 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value;; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint8, Count, Buffer); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint8, Count, Buffer); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint16, Count, Buffer); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint16, Count, Buffer); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint32, Count, Buffer); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint32, Count, Buffer); +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + return CpuIo->MemRead8 (PeiServices, CpuIo, (UINT64) Address); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + + CpuIo->MemWrite8 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + return CpuIo->MemRead16 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + CpuIo->MemWrite16 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + return CpuIo->MemRead32 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + CpuIo->MemWrite32 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & (sizeof (UINT64) - 1)) == 0); + return CpuIo->MemRead64 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + ASSERT (CpuIo != NULL); + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & 7) == 0); + CpuIo->MemWrite64 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} diff --git a/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c new file mode 100644 index 000000000..f4ee7c37f --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c @@ -0,0 +1,412 @@ +/** @file + I/O Library MMIO Buffer Functions. + The implementations are based on EFI_PEI_SERVICE->CpuIo interface. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include + +/** + Copy data from MMIO region to system memory by using 8-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 8-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = Buffer; + + while (Length-- != 0) { + *(Buffer++) = MmioRead8 (StartAddress++); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 16-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 16-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 32-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 32-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 64-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 64-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length != 0) { + *(Buffer++) = MmioRead64 (StartAddress); + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 8-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 8-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioWriteBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT8 *Buffer + ) +{ + VOID* ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = (UINT8 *) Buffer; + + while (Length-- != 0) { + MmioWrite8 (StartAddress++, *(Buffer++)); + } + + return ReturnBuffer; + +} + +/** + Copy data from system memory to MMIO region by using 16-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 16-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioWriteBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = (UINT16 *) Buffer; + + while (Length != 0) { + MmioWrite16 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 32-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 32-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioWriteBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = (UINT32 *) Buffer; + + while (Length != 0) { + MmioWrite32 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from system memory to MMIO region by using 64-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 64-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer The pointer to a system memory buffer containing the data to write. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioWriteBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = (UINT64 *) Buffer; + + while (Length != 0) { + MmioWrite64 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + diff --git a/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf new file mode 100644 index 000000000..8176edf33 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf @@ -0,0 +1,43 @@ +## @file +# Instance of I/O Library using CPU I/O PPI. +# +# I/O Library implementation that uses the CPU I/O PPI for I/O +# and MMIO operations. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiIoLibCpuIo + MODULE_UNI_FILE = PeiIoLibCpuIo.uni + FILE_GUID = b2585b69-fb63-4220-844a-8fbea8bf01af + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib|PEIM PEI_CORE SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + IoHighLevel.c + IoLib.c + IoLibMmioBuffer.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PeiServicesTablePointerLib + BaseLib + DebugLib + +[Depex.common.PEIM] + gEfiPeiCpuIoPpiInstalledGuid + diff --git a/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni new file mode 100644 index 000000000..a9e16fe1d --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of I/O Library using CPU I/O PPI. +// +// I/O Library implementation that uses the CPU I/O PPI for I/O +// and MMIO operations. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of I/O Library using CPU I/O PPI" + +#string STR_MODULE_DESCRIPTION #language en-US "I/O Library implementation that uses the CPU I/O PPI for I/O and MMIO operations." + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 000000000..b3f9df74f --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,842 @@ +/** @file + Support routines for memory allocation routines + based on PeiService for PEI phase drivers. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include +#include +#include +#include + + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + + return (VOID *) (UINTN) Memory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiBootServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiReservedMemoryType, Pages); +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment + specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then + NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = PeiServicesAllocatePages (MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = PeiServicesFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = PeiServicesFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + // + // If we need lots of small runtime/reserved memory type from PEI in the future, + // we can consider providing a more complex algorithm that allocates runtime pages and + // provide pool allocations from those pages. + // + return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize)); +} + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Buffer; + + Status = PeiServicesAllocatePool (AllocationSize, &Buffer); + if (EFI_ERROR (Status)) { + Buffer = NULL; + } + return Buffer; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiReservedMemoryType, AllocationSize); +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer + with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid + buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request, + then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = AllocatePool (AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = AllocatePool (AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiBootServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer); +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + // + // PEI phase does not support to free pool, so leave it as NOP. + // +} + + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf new file mode 100644 index 000000000..f6a670871 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf @@ -0,0 +1,40 @@ +## @file +# Instance of Memory Allocation Library using PEI Services. +# +# Memory Allocation Library that uses PEI Services to allocate memory. +# Free operations are ignored. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiMemoryAllocationLib + MODULE_UNI_FILE = PeiMemoryAllocationLib.uni + FILE_GUID = b694e0dc-cd4e-4b30-885b-9c164ed3e74a + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryAllocationLib|PEIM PEI_CORE SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + MemoryAllocationLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + BaseMemoryLib + PeiServicesLib + HobLib + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni new file mode 100644 index 000000000..2bc93f937 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Memory Allocation Library using PEI Services. +// +// Memory Allocation Library that uses PEI Services to allocate memory. +// Free operations are ignored. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library using PEI Services" + +#string STR_MODULE_DESCRIPTION #language en-US "Memory Allocation Library that uses PEI Services to allocate memory. Free operations are ignored." + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c new file mode 100644 index 000000000..180c11bea --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c @@ -0,0 +1,65 @@ +/** @file + Base Memory Library functions implementation bases on PeiServcie. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function wraps the gPS->CopyMem (). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + (*GetPeiServicesTablePointer ())->CopyMem ( + Destination, + (VOID*)Source, + Length + ); + return Destination; +} + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function wraps the gPS->SetMem (). + + @param Buffer Memory to set. + @param Size The number of bytes to set. + @param Value Value of the set operation. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + (*GetPeiServicesTablePointer ())->SetMem ( + Buffer, + Size, + Value + ); + return Buffer; +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c new file mode 100644 index 000000000..f646850ed --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c @@ -0,0 +1,283 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT16*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT32*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT64*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer + @param SourceBuffer The second memory buffer + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + Pointer = (CONST UINT8*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + Pointer = (CONST UINT16*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + Pointer = (CONST UINT32*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + Pointer = (CONST UINT64*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + CONST UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < Length; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h new file mode 100644 index 000000000..43d555a98 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h @@ -0,0 +1,243 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include + +#include +#include +#include +#include + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function wraps the (*PeiServices)->CopyMem (). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ); + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function wraps the (*PeiServices)->SetMem (). + + @param Buffer The memory to set. + @param Size The number of bytes to set. + @param Value Value of the set operation. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer + @param SourceBuffer The second memory buffer + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence, or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf b/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf new file mode 100644 index 000000000..ead38528b --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf @@ -0,0 +1,55 @@ +## @file +# Instance of Base Memory Library using PEI Services. +# +# Base Memory Library implementation that uses PEI Services +# where possible for size reduction. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiMemoryLib + MODULE_UNI_FILE = PeiMemoryLib.uni + FILE_GUID = 3a9759d2-53bc-4eb2-abcd-c93099419063 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib|PEIM + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGeneric.c + MemLibGuid.c + MemLib.c + MemLibInternals.h + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + DebugLib + PeiServicesTablePointerLib + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni b/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni new file mode 100644 index 000000000..206a2e0d6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library using PEI Services. +// +// Base Memory Library implementation that uses PEI Services +// where possible for size reduction. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library using PEI Services" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library implementation that uses PEI Services where possible, for size reduction." + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c new file mode 100644 index 000000000..5d85a295e --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c new file mode 100644 index 000000000..fb7073ac9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c new file mode 100644 index 000000000..9e9d663f7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c new file mode 100644 index 000000000..39ec8cb0d --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c new file mode 100644 index 000000000..916a2c084 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c @@ -0,0 +1,1619 @@ +/** @file +Implementation of PcdLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + + + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/** + Retrieve the PCD_PPI pointer. + + This function is to locate PCD_PPI PPI via PeiService. + If fail to locate PCD_PPI, then ASSERT_EFI_ERROR(). + + @retval PCD_PPI * The pointer to the PCD_PPI. + +**/ +PCD_PPI * +GetPcdPpiPointer ( + VOID + ) +{ + EFI_STATUS Status; + PCD_PPI *PcdPpi; + + Status = PeiServicesLocatePpi (&gPcdPpiGuid, 0, NULL, (VOID **)&PcdPpi); + ASSERT_EFI_ERROR (Status); + + return PcdPpi; +} + +/** + Retrieve the pointer of EFI_PEI_PCD_PPI defined in PI 1.2 Vol 3. + + This function is to locate EFI_PEI_PCD_PPI PPI via PeiService. + If fail to locate EFI_PEI_PCD_PPI, then ASSERT_EFI_ERROR(). + + @retval EFI_PEI_PCD_PPI * The pointer to the EFI_PEI_PCD_PPI. + +**/ +EFI_PEI_PCD_PPI * +GetPiPcdPpiPointer ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_PCD_PPI *PiPcdPpi; + + Status = PeiServicesLocatePpi (&gEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&PiPcdPpi); + ASSERT_EFI_ERROR (Status); + + return PiPcdPpi; +} + +/** + Retrieve the GET_PCD_INFO_PPI pointer. + + This function is to locate GET_PCD_INFO_PPI PPI via PeiService. + If fail to locate GET_PCD_INFO_PPI, then ASSERT_EFI_ERROR(). + + @retval GET_PCD_INFO_PPI * The pointer to the GET_PCD_INFO_PPI. + +**/ +GET_PCD_INFO_PPI * +GetPcdInfoPpiPointer ( + VOID + ) +{ + EFI_STATUS Status; + GET_PCD_INFO_PPI *PcdInfoPpi; + + Status = PeiServicesLocatePpi (&gGetPcdInfoPpiGuid, 0, NULL, (VOID **)&PcdInfoPpi); + ASSERT_EFI_ERROR (Status); + + return PcdInfoPpi; +} + +/** + Retrieve the pointer of EFI_GET_PCD_INFO_PPI defined in PI 1.2.1 Vol 3. + + This function is to locate EFI_GET_PCD_INFO_PPI PPI via PeiService. + If fail to locate EFI_GET_PCD_INFO_PPI, then ASSERT_EFI_ERROR(). + + @retval EFI_GET_PCD_INFO_PPI * The pointer to the EFI_GET_PCD_INFO_PPI. + +**/ +EFI_GET_PCD_INFO_PPI * +GetPiPcdInfoPpiPointer ( + VOID + ) +{ + EFI_STATUS Status; + EFI_GET_PCD_INFO_PPI *PiPcdInfoPpi; + + Status = PeiServicesLocatePpi (&gEfiGetPcdInfoPpiGuid, 0, NULL, (VOID **)&PiPcdInfoPpi); + ASSERT_EFI_ERROR (Status); + + return PiPcdInfoPpi; +} + +/** + This function provides a means by which SKU support can be established in the PCD infrastructure. + + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param SkuId The SKU value that will be used when the PCD service retrieves + and sets values associated with a PCD token. + + @return Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + GetPiPcdPpiPointer()->SetSku (SkuId); + + return SkuId; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->Get8 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->Get16 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->Get32 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->Get64 (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->GetPtr (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->GetBool (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + return (GetPcdPpiPointer ())->GetSize (TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Get8 (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Get16 (Guid, TokenNumber); +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Get32 (Guid, TokenNumber); +} + + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + return (GetPiPcdPpiPointer ())->Get64 (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->GetPtr (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + return (GetPiPcdPpiPointer ())->GetBool (Guid, TokenNumber); +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + Returns the size of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + return (GetPiPcdPpiPointer ())->GetSize (Guid, TokenNumber); +} + + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + (GetPcdPpiPointer ())->Set8 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + (GetPcdPpiPointer ())->Set16 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + (GetPcdPpiPointer ())->Set32 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + (GetPcdPpiPointer ())->Set64 (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value + specified by Buffer and SizeOfBuffer. Buffer is returned. + If SizeOfBuffer is greater than the maximum size support by TokenNumber, + then set SizeOfBuffer to the maximum size supported by TokenNumber and + return NULL to indicate that the set operation was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and NULL must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN InputSizeOfBuffer; + + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + InputSizeOfBuffer = *SizeOfBuffer; + Status = (GetPcdPpiPointer ())->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer); + if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) { + return NULL; + } + + return (VOID *) Buffer; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + (GetPcdPpiPointer ())->SetBool (TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return Return the value that was set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (Guid != NULL); + + (GetPiPcdPpiPointer ())->Set8 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return Return the value that was set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (Guid != NULL); + + (GetPiPcdPpiPointer ())->Set16 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return Return the value that was set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (Guid != NULL); + + (GetPiPcdPpiPointer ())->Set32 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return Return the value that was set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (Guid != NULL); + + (GetPiPcdPpiPointer ())->Set64 (Guid, TokenNumber, Value); + + return Value; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size + supported by TokenNumber and return NULL to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return Return the pinter to the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN InputSizeOfBuffer; + + ASSERT (SizeOfBuffer != NULL); + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + ASSERT (Guid != NULL); + + InputSizeOfBuffer = *SizeOfBuffer; + Status = (GetPiPcdPpiPointer ())->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer); + if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) { + return NULL; + } + + return Buffer; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @return Return the value that was set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (Guid != NULL); + + (GetPiPcdPpiPointer ())->SetBool (Guid, TokenNumber, Value); + + return Value; +} +#endif + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet8S ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return (GetPcdPpiPointer ())->Set8 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet16S ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return (GetPcdPpiPointer ())->Set16 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet32S ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return (GetPcdPpiPointer ())->Set32 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet64S ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return (GetPcdPpiPointer ())->Set64 (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and EFI_INVALID_PARAMETER must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetPtrS ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + return (GetPcdPpiPointer ())->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetBoolS ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return (GetPcdPpiPointer ())->SetBool (TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx8S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Set8 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx16S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Set16 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx32S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Set32 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx64S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->Set64 (Guid, TokenNumber, Value); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExPtrS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + ASSERT (Guid != NULL); + + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + return (GetPiPcdPpiPointer ())->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer); +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExBoolS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (Guid != NULL); + + return (GetPiPcdPpiPointer ())->SetBool (Guid, TokenNumber, Value); +} + +/** + Set up a notification function that is called when a specified token is set. + + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + If NULL, then the default token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = (GetPiPcdPpiPointer ())->CallbackOnSet (Guid, TokenNumber, (EFI_PEI_PCD_PPI_CALLBACK) NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + + Disable a notification function that was previously established with LibPcdCallbackOnSet(). + If NotificationFunction is NULL, then ASSERT(). + If LibPcdCallbackOnSet() was not previously called with Guid, TokenNumber, + and NotificationFunction, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = (GetPiPcdPpiPointer ())->CancelCallback (Guid, TokenNumber, (EFI_PEI_PCD_PPI_CALLBACK) NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Retrieves the next token in a token space. + + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. + + If TokenNumber is not 0 and is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] TokenNumber The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @return The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber + ) +{ + EFI_STATUS Status; + + Status = (GetPiPcdPpiPointer ())->GetNextToken (Guid, &TokenNumber); + ASSERT (!EFI_ERROR (Status) || TokenNumber == 0); + + return TokenNumber; +} + + +/** + Used to retrieve the list of available PCD token space GUIDs. + + Returns the PCD token space GUID that follows TokenSpaceGuid in the list of token spaces + in the platform. + If TokenSpaceGuid is NULL, then a pointer to the first PCD token spaces returned. + If TokenSpaceGuid is the last PCD token space GUID in the list, then NULL is returned. + + @param TokenSpaceGuid The pointer to the a PCD token space GUID + + @return The next valid token namespace. + +**/ +GUID * +EFIAPI +LibPcdGetNextTokenSpace ( + IN CONST GUID *TokenSpaceGuid + ) +{ + (GetPiPcdPpiPointer ())->GetNextTokenSpace (&TokenSpaceGuid); + + return (GUID *) TokenSpaceGuid; +} + + + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtr ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return (VOID *) Buffer; +} + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrS ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return RETURN_SUCCESS; +} + + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtrAndSize ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return (VOID *) Buffer; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrAndSizeS ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return RETURN_SUCCESS; +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the default token space specified, then ASSERT(). + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfo ( + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + EFI_STATUS Status; + + Status = GetPcdInfoPpiPointer()->GetInfo (TokenNumber, (EFI_PCD_INFO *) PcdInfo); + ASSERT_EFI_ERROR (Status); +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfoEx ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + EFI_STATUS Status; + + Status = GetPiPcdInfoPpiPointer()->GetInfo (Guid, TokenNumber, (EFI_PCD_INFO *) PcdInfo); + ASSERT_EFI_ERROR (Status); +} + +/** + Retrieve the currently set SKU Id. + + @return The currently set SKU Id. If the platform has not set at a SKU Id, then the + default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU + Id is returned. +**/ +UINTN +EFIAPI +LibPcdGetSku ( + VOID + ) +{ + return GetPiPcdInfoPpiPointer()->GetSku (); +} diff --git a/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf new file mode 100644 index 000000000..75d0a630d --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf @@ -0,0 +1,61 @@ +## @file +# Instance of PCD Library using PCD PPI. +# +# There are two PCD PPIs as follows: +# 1) PCD_PPI +# It is EDKII implementation which support Dynamic/DynamicEx Pcds. +# 2) EFI_PEI_PCD_PPI +# It is defined by PI specification 1.2, Vol 3 which only support dynamicEx +# type Pcd. +# For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI. +# This library instance uses the PCD_PPI to handle dynamic PCD request and use +# EFI_PEI_PCD_PPI to handle dynamicEx type PCD. +# +# This library instance assume the PCD_PPI and EFI_PEI_PCD_PPI are both installed early. +# +# PCD Library that uses the PCD PPI to access Dynamic and DynamicEx PCD entries +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiPcdLib + MODULE_UNI_FILE = PeiPcdLib.uni + FILE_GUID = 9dbf6f25-0da2-4a1d-8e12-e78de6ab4d0e + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PcdLib|PEIM PEI_CORE SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiPcdLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + PeiServicesLib + DebugLib + + +[Ppis] + gPcdPpiGuid ## SOMETIMES_CONSUMES + gEfiPeiPcdPpiGuid ## CONSUMES + gGetPcdInfoPpiGuid ## SOMETIMES_CONSUMES + gEfiGetPcdInfoPpiGuid ## SOMETIMES_CONSUMES + +[Depex.common.PEIM] + gEfiPeiPcdPpiGuid + diff --git a/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni new file mode 100644 index 000000000..102a837a5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni @@ -0,0 +1,28 @@ +// /** @file +// Instance of PCD Library using PCD PPI. +// +// There are two PCD PPIs as follows: +// 1) PCD_PPI +// It is EDKII implementation which support Dynamic/DynamicEx Pcds. +// 2) EFI_PEI_PCD_PPI +// It is defined by PI specification 1.2, Vol 3 which only support dynamicEx +// type Pcd. +// For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI. +// This library instance uses the PCD_PPI to handle dynamic PCD request and use +// EFI_PEI_PCD_PPI to handle dynamicEx type PCD. +// +// This library instance assume the PCD_PPI and EFI_PEI_PCD_PPI are both installed early. +// +// PCD Library that uses the PCD PPI to access Dynamic and DynamicEx PCD entries +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCD Library for PEI" + +#string STR_MODULE_DESCRIPTION #language en-US "There are two PCD PPIs as follows: 1) PCD_PPI: It is EDKII implementation which support Dynamic/DynamicEx Pcds. 2) EFI_PEI_PCD_PPI: It is defined by PI Specification 1.2, Vol 3, which only support dynamicEx type Pcd. For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI. This library instance uses the PCD_PPI to handle dynamic PCD request and use EFI_PEI_PCD_PPI to handle dynamicEx type PCD. This library instance assumes that PCD_PPI and EFI_PEI_PCD_PPI are both installed early. The PCD Library that uses the PCD PPI to access Dynamic and DynamicEx PCD entries." + diff --git a/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c new file mode 100644 index 000000000..b9ed2d2d9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c @@ -0,0 +1,1415 @@ +/** @file + PCI Library using PCI CFG2 PPI. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A,M) \ + ASSERT (((A) & (~0xfffffff | (M))) == 0) + +/** + Translate PCI Lib address into format of PCI CFG2 PPI. + + @param A The address that encodes the PCI Bus, Device, Function and + Register. + +**/ +#define PCI_TO_PCICFG2_ADDRESS(A) \ + ((((A) << 4) & 0xff000000) | (((A) >> 4) & 0x00000700) | (((A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) + +/** + Internal worker function to read a PCI configuration register. + + This function wraps EFI_PEI_PCI_CFG2_PPI.Read() service. + It reads and returns the PCI configuration register specified by Address, + the width of data is specified by Width. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to read + + @return The value read from the PCI configuration register. + +**/ +UINT32 +PeiPciLibPciCfg2ReadWorker ( + IN UINTN Address, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width + ) +{ + EFI_STATUS Status; + UINT32 Data; + CONST EFI_PEI_PCI_CFG2_PPI *PciCfg2Ppi; + UINT64 PciCfg2Address; + + Status = PeiServicesLocatePpi (&gEfiPciCfg2PpiGuid, 0, NULL, (VOID **) &PciCfg2Ppi); + ASSERT_EFI_ERROR (Status); + ASSERT (PciCfg2Ppi != NULL); + + PciCfg2Address = PCI_TO_PCICFG2_ADDRESS (Address); + PciCfg2Ppi->Read ( + GetPeiServicesTablePointer (), + PciCfg2Ppi, + Width, + PciCfg2Address, + &Data + ); + + return Data; +} + +/** + Internal worker function to writes a PCI configuration register. + + This function wraps EFI_PEI_PCI_CFG2_PPI.Write() service. + It writes the PCI configuration register specified by Address with the + value specified by Data. The width of data is specified by Width. + Data is returned. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +PeiPciLibPciCfg2WriteWorker ( + IN UINTN Address, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT32 Data + ) +{ + EFI_STATUS Status; + CONST EFI_PEI_PCI_CFG2_PPI *PciCfg2Ppi; + UINT64 PciCfg2Address; + + Status = PeiServicesLocatePpi (&gEfiPciCfg2PpiGuid, 0, NULL, (VOID **) &PciCfg2Ppi); + ASSERT_EFI_ERROR (Status); + ASSERT (PciCfg2Ppi != NULL); + + PciCfg2Address = PCI_TO_PCICFG2_ADDRESS (Address); + PciCfg2Ppi->Write ( + GetPeiServicesTablePointer (), + PciCfg2Ppi, + Width, + PciCfg2Address, + &Data + ); + + return Data; +} + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + return RETURN_UNSUPPORTED; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) PeiPciLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) PeiPciLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) ((PciRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciWrite8 ( + Address, + BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldOr8 (PciRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciWrite8 ( + Address, + BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldAndThenOr8 (PciRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) PeiPciLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) PeiPciLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) ((PciRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciWrite16 ( + Address, + BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciWrite16 ( + Address, + BitFieldAnd16 (PciRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldAndThenOr16 (PciRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return PeiPciLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return PeiPciLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, (PciRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciWrite32 ( + Address, + BitFieldWrite32 (PciRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldOr32 (PciRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciWrite32 ( + Address, + BitFieldAnd32 (PciRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldAndThenOr32 (PciRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf new file mode 100644 index 000000000..bf945a1f8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf @@ -0,0 +1,51 @@ +## @file +# PCI Library that layers on top of the PCI CFG2 PPI. +# +# This library produces the APIs from the PCI Library and implements +# these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more EFI_PEI_PCI CFG2 +# PPIs are typically produced by a chipset specific PEIM. This library only uses +# the first PPI found, so this library instance should only be used platforms +# with a single PCI segment. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiPciLibPciCfg2 + MODULE_UNI_FILE = PeiPciLibPciCfg2.uni + FILE_GUID = FA3AD693-D58A-4619-960B-8EE85C914870 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib|PEIM SEC PEI_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PciLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + PeiServicesTablePointerLib + BaseLib + DebugLib + PeiServicesLib + +[Ppis] + gEfiPciCfg2PpiGuid ## CONSUMES + +[Depex.common.PEIM] + gEfiPciCfg2PpiGuid + diff --git a/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni new file mode 100644 index 000000000..132f4d877 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni @@ -0,0 +1,20 @@ +// /** @file +// PCI Library that layers on top of the PCI CFG2 PPI. +// +// This library produces the APIs from the PCI Library and implements +// these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more EFI_PEI_PCI CFG2 +// PPIs are typically produced by a chipset specific PEIM. This library only uses +// the first PPI found, so this library instance should only be used platforms +// with a single PCI segment. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCI Library that layers on top of the PCI CFG2 PPI" + +#string STR_MODULE_DESCRIPTION #language en-US "This library produces the APIs from the PCI Library, and implements these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more EFI_PEI_PCI CFG2 PPIs are typically produced by a chipset-specific PEIM. This library only uses the first PPI found, so this library instance should only be used on platforms with a single PCI segment." + diff --git a/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c new file mode 100644 index 000000000..1128c917f --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c @@ -0,0 +1,1407 @@ +/** @file + PCI Segment Library implementation using PCI CFG2 PPI. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include + +/** + Assert the validity of a PCI Segment address. + A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63 + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \ + ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0) + +/** + Translate PCI Lib address into format of PCI CFG2 PPI. + + @param A The address that encodes the PCI Bus, Device, Function and + Register. + +**/ +#define PCI_TO_PCICFG2_ADDRESS(A) \ + ((((UINT32)(A) << 4) & 0xff000000) | (((UINT32)(A) >> 4) & 0x00000700) | (((UINT32)(A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) + +/** + Gets PCI CFG2 PPI. + + This internal function retrieves PCI CFG2 PPI from PPI database. + + @param Address The address that encodes the PCI Segment, Bus, Device, + Function and Register. + + @return The pointer to PCI CFG2 PPI. + +**/ +EFI_PEI_PCI_CFG2_PPI * +InternalGetPciCfg2Ppi ( + IN UINT64 Address + ) +{ + EFI_STATUS Status; + UINTN Instance; + EFI_PEI_PCI_CFG2_PPI *PciCfg2Ppi; + UINT64 SegmentNumber; + + Instance = 0; + PciCfg2Ppi = NULL; + SegmentNumber = BitFieldRead64 (Address, 32, 63); + + // + // Loop through all instances of the PPI and match segment number + // + do { + Status = PeiServicesLocatePpi( + &gEfiPciCfg2PpiGuid, + Instance, + NULL, + (VOID**) &PciCfg2Ppi + ); + ASSERT_EFI_ERROR (Status); + Instance++; + } while (PciCfg2Ppi->Segment != SegmentNumber); + + return PciCfg2Ppi; +} + +/** + Internal worker function to read a PCI configuration register. + + This function wraps EFI_PEI_PCI_CFG2_PPI.Read() service. + It reads and returns the PCI configuration register specified by Address, + the width of data is specified by Width. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to read + + @return The value read from the PCI configuration register. + +**/ +UINT32 +PeiPciSegmentLibPciCfg2ReadWorker ( + IN UINT64 Address, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width + ) +{ + UINT32 Data; + CONST EFI_PEI_PCI_CFG2_PPI *PciCfg2Ppi; + UINT64 PciCfg2Address; + + PciCfg2Ppi = InternalGetPciCfg2Ppi (Address); + PciCfg2Address = PCI_TO_PCICFG2_ADDRESS (Address); + PciCfg2Ppi->Read ( + GetPeiServicesTablePointer (), + PciCfg2Ppi, + Width, + PciCfg2Address, + &Data + ); + + return Data; +} + +/** + Internal worker function to writes a PCI configuration register. + + This function wraps EFI_PEI_PCI_CFG2_PPI.Write() service. + It writes the PCI configuration register specified by Address with the + value specified by Data. The width of data is specifed by Width. + Data is returned. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +PeiPciSegmentLibPciCfg2WriteWorker ( + IN UINT64 Address, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT32 Data + ) +{ + CONST EFI_PEI_PCI_CFG2_PPI *PciCfg2Ppi; + UINT64 PciCfg2Address; + + PciCfg2Ppi = InternalGetPciCfg2Ppi (Address); + PciCfg2Address = PCI_TO_PCICFG2_ADDRESS (Address); + PciCfg2Ppi->Write ( + GetPeiServicesTablePointer (), + PciCfg2Ppi, + Width, + PciCfg2Address, + &Data + ); + + return Data; +} + +/** + Register a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + return RETURN_UNSUPPORTED; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) PeiPciSegmentLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) PeiPciSegmentLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) PeiPciSegmentLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) PeiPciSegmentLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PeiPciSegmentLibPciCfg2ReadWorker (Address, EfiPeiPciCfgWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return PeiPciSegmentLibPciCfg2WriteWorker (Address, EfiPeiPciCfgWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + + Reads the 32-bit PCI configuration register specified by Address, performs a bitwise + AND between the read result and the value specified by AndData, and writes the result + to the 32-bit PCI configuration register specified by Address. The value written to + the PCI configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + } + + return ReturnValue; +} + + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf new file mode 100644 index 000000000..0b832c172 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf @@ -0,0 +1,48 @@ +## @file +# PCI Segment Library that layers on top of the PCI CFG2 PPI. +# +# This library produces the APIs from the PCI Segment Library and +# implements these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more +# EFI_PEI_PCI CFG2 PPIs are typically produced by a chipset specific PEIM. +# This library instance should only be used platforms with multiple PCI segments. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiPciSegmentLibPciCfg2 + MODULE_UNI_FILE = PeiPciSegmentLibPciCfg2.uni + FILE_GUID = 254901AD-7DB7-45f8-93C8-93D579398D9F + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib|PEIM SEC PEI_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PciSegmentLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PeiServicesTablePointerLib + BaseLib + DebugLib + PeiServicesLib + +[Ppis] + gEfiPciCfg2PpiGuid ## CONSUMES + +[Depex.common.PEIM] + gEfiPciCfg2PpiGuid + diff --git a/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni new file mode 100644 index 000000000..b5c7ab98d --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni @@ -0,0 +1,19 @@ +// /** @file +// PCI Segment Library that layers on top of the PCI CFG2 PPI. +// +// This library produces the APIs from the PCI Segment Library and +// implements these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more +// EFI_PEI_PCI CFG2 PPIs are typically produced by a chipset specific PEIM. +// This library instance should only be used platforms with multiple PCI segments. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCI Segment Library that layers on top of the PCI CFG2 PPI" + +#string STR_MODULE_DESCRIPTION #language en-US "This library produces the APIs from the PCI Segment Library and implements these APIs by calling into the EFI_PEI_PCI CFG2 PPI. One or more EFI_PEI_PCI CFG2 PPIs are typically produced by a chipset-specific PEIM. This library instance should only be used on platforms with multiple PCI segments." + diff --git a/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c new file mode 100644 index 000000000..d2833585b --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c @@ -0,0 +1,52 @@ +/** @file + Resource Publication Library that uses PEI Core Services to publish system memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include + + +#include +#include +#include + + +/** + Declares the presence of permanent system memory in the platform. + + Declares that the system memory buffer specified by MemoryBegin and MemoryLength + as permanent memory that may be used for general purpose use by software. + The amount of memory available to software may be less than MemoryLength + if published memory has alignment restrictions. + If MemoryLength is 0, then ASSERT(). + If MemoryLength is greater than (MAX_ADDRESS - MemoryBegin + 1), then ASSERT(). + + @param MemoryBegin The start address of the memory being declared. + @param MemoryLength The number of bytes of memory being declared. + + @retval RETURN_SUCCESS The memory buffer was published. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to publish the memory buffer + +**/ +RETURN_STATUS +EFIAPI +PublishSystemMemory ( + IN PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + EFI_STATUS Status; + + ASSERT (MemoryLength > 0); + ASSERT (MemoryLength <= (MAX_ADDRESS - MemoryBegin + 1)); + + Status = PeiServicesInstallPeiMemory (MemoryBegin, MemoryLength); + + return (RETURN_STATUS) Status; +} + diff --git a/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf new file mode 100644 index 000000000..ac239dff0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf @@ -0,0 +1,37 @@ +## @file +# Instance of Resource Publication Library using PEI Services. +# +# Resource Publication Library that uses PEI Services to publish system memory. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiResourcePublicationLib + MODULE_UNI_FILE = PeiResourcePublicationLib.uni + FILE_GUID = e8d6390d-e190-4957-9ab6-d47d51b01336 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = ResourcePublicationLib|PEIM SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiResourcePublicationLib.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + PeiServicesLib + diff --git a/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni new file mode 100644 index 000000000..38312948f --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Resource Publication Library using PEI Services. +// +// Resource Publication Library that uses PEI Services to publish system memory. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Resource Publication Library using PEI Services" + +#string STR_MODULE_DESCRIPTION #language en-US "This Resource Publication Library uses PEI Services to publish system memory." + diff --git a/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c new file mode 100644 index 000000000..e8eaed71c --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c @@ -0,0 +1,809 @@ +/** @file + Implementation for PEI Services Library. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + This service enables a given PEIM to register an interface into the PEI Foundation. + + @param PpiList A pointer to the list of interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have the + EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiServicesInstallPpi ( + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->InstallPpi (PeiServices, PpiList); +} + +/** + This service enables PEIMs to replace an entry in the PPI database with an alternate entry. + + @param OldPpi The pointer to the old PEI PPI Descriptors. + @param NewPpi The pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The OldPpi or NewPpi is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have the + EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + @retval EFI_NOT_FOUND The PPI for which the reinstallation was requested has not been + installed. + +**/ +EFI_STATUS +EFIAPI +PeiServicesReInstallPpi ( + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->ReInstallPpi (PeiServices, OldPpi, NewPpi); +} + +/** + This service enables PEIMs to discover a given instance of an interface. + + @param Guid A pointer to the GUID whose corresponding interface needs to be + found. + @param Instance The N-th instance of the interface that is required. + @param PpiDescriptor A pointer to instance of the EFI_PEI_PPI_DESCRIPTOR. + @param Ppi A pointer to the instance of the interface. + + @retval EFI_SUCCESS The interface was successfully returned. + @retval EFI_NOT_FOUND The PPI descriptor is not found in the database. + +**/ +EFI_STATUS +EFIAPI +PeiServicesLocatePpi ( + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, OPTIONAL + IN OUT VOID **Ppi + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->LocatePpi (PeiServices, Guid, Instance, PpiDescriptor, Ppi); +} + +/** + This service enables PEIMs to register a given service to be invoked when another service is + installed or reinstalled. + + @param NotifyList A pointer to the list of notification interfaces + that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The NotifyList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI notify descriptors in the list do + not have the EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES + bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiServicesNotifyPpi ( + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->NotifyPpi (PeiServices, NotifyList); +} + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesGetBootMode ( + OUT EFI_BOOT_MODE *BootMode + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->GetBootMode (PeiServices, BootMode); +} + +/** + This service enables PEIMs to update the boot mode variable. + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiServicesSetBootMode ( + IN EFI_BOOT_MODE BootMode + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->SetBootMode (PeiServices, BootMode); +} + +/** + This service enables a PEIM to ascertain the address of the list of HOBs in memory. + + @param HobList A pointer to the list of HOBs that the PEI Foundation + will initialize. + + @retval EFI_SUCCESS The list was successfully returned. + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +EFI_STATUS +EFIAPI +PeiServicesGetHobList ( + OUT VOID **HobList + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->GetHobList (PeiServices, HobList); +} + +/** + This service enables PEIMs to create various types of HOBs. + + @param Type The type of HOB to be installed. + @param Length The length of the HOB to be added. + @param Hob The address of a pointer that will contain the + HOB header. + + @retval EFI_SUCCESS The HOB was successfully created. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiServicesCreateHob ( + IN UINT16 Type, + IN UINT16 Length, + OUT VOID **Hob + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->CreateHob (PeiServices, Type, Length, Hob); +} + +/** + This service enables PEIMs to discover additional firmware volumes. + + @param Instance This instance of the firmware volume to find. The + value 0 is the Boot Firmware Volume (BFV). + @param VolumeHandle Handle of the firmware volume header of the volume + to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindNextVolume (PeiServices, Instance, VolumeHandle); +} + +/** + This service enables PEIMs to discover additional firmware files. + + @param SearchType A filter to find files only of this type. + @param VolumeHandle The pointer to the firmware volume header of the + volume to search. This parameter must point to a + valid FFS volume. + @param FileHandle Handle of the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindNextFile (PeiServices, SearchType, VolumeHandle, FileHandle); +} + +/** + This service enables PEIMs to discover sections of a given type within a valid FFS file. + + @param SectionType The value of the section type to find. + @param FileHandle A pointer to the file header that contains the set + of sections to be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindSectionData (PeiServices, SectionType, FileHandle, SectionData); +} + +/** + This service enables PEIMs to discover sections of a given instance and type within a valid FFS file. + + @param SectionType The value of the section type to find. + @param SectionInstance Section instance to find. + @param FileHandle A pointer to the file header that contains the set + of sections to be searched. + @param SectionData A pointer to the discovered section, if successful. + @param AuthenticationStatus A pointer to the authentication status for this section. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsFindSectionData3 ( + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FindSectionData3 (PeiServices, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus); +} + +/** + This service enables PEIMs to register the permanent memory configuration + that has been initialized with the PEI Foundation. + + @param MemoryBegin The value of a region of installed memory. + @param MemoryLength The corresponding length of a region of installed memory. + + @retval EFI_SUCCESS The region was successfully installed in a HOB. + @retval EFI_INVALID_PARAMETER MemoryBegin and MemoryLength are illegal for this system. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiServicesInstallPeiMemory ( + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->InstallPeiMemory (PeiServices, MemoryBegin, MemoryLength); +} + +/** + This service enables PEIMs to allocate memory. + + @param MemoryType Type of memory to allocate. + @param Pages The number of pages to allocate. + @param Memory Pointer of memory allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +PeiServicesAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->AllocatePages (PeiServices, MemoryType, Pages, Memory); +} + +/** + This service enables PEIMs to free memory. + + @param Memory Memory to be freed. + @param Pages The number of pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiServicesFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FreePages (PeiServices, Memory, Pages); +} + +/** + This service allocates memory from the Hand-Off Block (HOB) heap. + + @param Size The number of bytes to allocate from the pool. + @param Buffer If the call succeeds, a pointer to a pointer to + the allocate buffer; otherwise, undefined. + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiServicesAllocatePool ( + IN UINTN Size, + OUT VOID **Buffer + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->AllocatePool (PeiServices, Size, Buffer); +} + +/** + Resets the entire platform. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_AVAILABLE_YET The service has not been installed yet. + +**/ +EFI_STATUS +EFIAPI +PeiServicesResetSystem ( + VOID + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->ResetSystem (PeiServices); +} + +/** + This service is a wrapper for the PEI Service RegisterForShadow(), except the + pointer to the PEI Services Table has been removed. See the Platform + Initialization Pre-EFI Initialization Core Interface Specification for details. + + @param FileHandle PEIM's file handle. Must be the currently + executing PEIM. + + @retval EFI_SUCCESS The PEIM was successfully registered for + shadowing. + + @retval EFI_ALREADY_STARTED The PEIM was previously + registered for shadowing. + + @retval EFI_NOT_FOUND The FileHandle does not refer to a + valid file handle. +**/ +EFI_STATUS +EFIAPI +PeiServicesRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +{ + return (*GetPeiServicesTablePointer())->RegisterForShadow (FileHandle); +} + +/** + This service is a wrapper for the PEI Service FfsGetFileInfo(), except the pointer to the PEI Services + Table has been removed. See the Platform Initialization Pre-EFI Initialization Core Interface + Specification for details. + + @param FileHandle The handle of the file. + + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + return (*GetPeiServicesTablePointer())->FfsGetFileInfo (FileHandle, FileInfo); +} + +/** + This service is a wrapper for the PEI Service FfsGetFileInfo2(), except the pointer to the PEI Services + Table has been removed. See the Platform Initialization Pre-EFI Initialization Core Interface + Specification for details. + + @param FileHandle The handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo2 ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ) +{ + return (*GetPeiServicesTablePointer())->FfsGetFileInfo2 (FileHandle, FileInfo); +} + +/** + This service is a wrapper for the PEI Service FfsFindByName(), except the pointer to the PEI Services + Table has been removed. See the Platform Initialization Pre-EFI Initialization Core Interface + Specification for details. + + @param FileName A pointer to the name of the file to + find within the firmware volume. + + @param VolumeHandle The firmware volume to search FileHandle + Upon exit, points to the found file's + handle or NULL if it could not be found. + @param FileHandle The pointer to found file handle + + @retval EFI_SUCCESS File was found. + + @retval EFI_NOT_FOUND File was not found. + + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or + FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN CONST EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return (*GetPeiServicesTablePointer())->FfsFindFileByName (FileName, VolumeHandle, FileHandle); +} + + +/** + This service is a wrapper for the PEI Service FfsGetVolumeInfo(), except the pointer to the PEI Services + Table has been removed. See the Platform Initialization Pre-EFI Initialization Core Interface + Specification for details. + + @param VolumeHandle Handle of the volume. + + @param VolumeInfo Upon exit, points to the volume's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + return (*GetPeiServicesTablePointer())->FfsGetVolumeInfo (VolumeHandle, VolumeInfo); +} + +/** + Install a EFI_PEI_FIRMWARE_VOLUME_INFO(2)_PPI instance so the PEI Core will be notified about a new firmware volume. + + This function allocates, initializes, and installs a new EFI_PEI_FIRMWARE_VOLUME_INFO(2)_PPI using + the parameters passed in to initialize the fields of the EFI_PEI_FIRMWARE_VOLUME_INFO(2)_PPI instance. + If the resources can not be allocated for EFI_PEI_FIRMWARE_VOLUME_INFO(2)_PPI, then ASSERT(). + If the EFI_PEI_FIRMWARE_VOLUME_INFO(2)_PPI can not be installed, then ASSERT(). + If NULL is specified for FvFormat, but FvInfo does not have the firmware file system 2 format, then ASSERT. + + @param InstallFvInfoPpi Install FvInfo Ppi if it is TRUE. Otherwise, install FvInfo2 Ppi. + @param FvFormat Unique identifier of the format of the memory-mapped + firmware volume. This parameter is optional and + may be NULL. If NULL is specified, the + EFI_FIRMWARE_FILE_SYSTEM2_GUID format is assumed. + @param FvInfo Points to a buffer which allows the + EFI_PEI_FIRMWARE_VOLUME_PPI to process the volume. + The format of this buffer is specific to the FvFormat. + For memory-mapped firmware volumes, this typically + points to the first byte of the firmware volume. + @param FvInfoSize The size, in bytes, of FvInfo. For memory-mapped + firmware volumes, this is typically the size of + the firmware volume. + @param ParentFvName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID name of the originating firmware + volume. Otherwise, this parameter must be NULL. + @param ParentFileName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID file name of the originating + firmware file. Otherwise, this parameter must be NULL. + @param AuthenticationStatus Authentication Status, it will be ignored if InstallFvInfoPpi is TRUE. +**/ +VOID +EFIAPI +InternalPeiServicesInstallFvInfoPpi ( + IN BOOLEAN InstallFvInfoPpi, + IN CONST EFI_GUID *FvFormat, OPTIONAL + IN CONST VOID *FvInfo, + IN UINT32 FvInfoSize, + IN CONST EFI_GUID *ParentFvName, OPTIONAL + IN CONST EFI_GUID *ParentFileName, OPTIONAL + IN UINT32 AuthenticationStatus + ) +{ + EFI_STATUS Status; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi; + EFI_PEI_PPI_DESCRIPTOR *FvInfoPpiDescriptor; + EFI_GUID *ParentFvNameValue; + EFI_GUID *ParentFileNameValue; + EFI_GUID *PpiGuid; + + ParentFvNameValue = NULL; + ParentFileNameValue = NULL; + if (InstallFvInfoPpi) { + // + // To install FvInfo Ppi. + // + FvInfoPpi = AllocateZeroPool (sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI)); + ASSERT (FvInfoPpi != NULL); + PpiGuid = &gEfiPeiFirmwareVolumeInfoPpiGuid; + } else { + // + // To install FvInfo2 Ppi. + // + FvInfoPpi = AllocateZeroPool (sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI)); + ASSERT (FvInfoPpi != NULL); + ((EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *) FvInfoPpi)->AuthenticationStatus = AuthenticationStatus; + PpiGuid = &gEfiPeiFirmwareVolumeInfo2PpiGuid; + } + + if (FvFormat != NULL) { + CopyGuid (&FvInfoPpi->FvFormat, FvFormat); + } else { + CopyGuid (&FvInfoPpi->FvFormat, &gEfiFirmwareFileSystem2Guid); + // + // Since the EFI_FIRMWARE_FILE_SYSTEM2_GUID format is assumed if NULL is specified for FvFormat, + // check the FileSystemGuid pointed by FvInfo against EFI_FIRMWARE_FILE_SYSTEM2_GUID to make sure + // FvInfo has the firmware file system 2 format. + // If the ASSERT really appears, FvFormat needs to be specified correctly, for example, + // EFI_FIRMWARE_FILE_SYSTEM3_GUID can be used for firmware file system 3 format, or + // ((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo)->FileSystemGuid can be just used for both + // firmware file system 2 and 3 format. + // + ASSERT (CompareGuid (&(((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo)->FileSystemGuid), &gEfiFirmwareFileSystem2Guid)); + } + FvInfoPpi->FvInfo = (VOID *) FvInfo; + FvInfoPpi->FvInfoSize = FvInfoSize; + if (ParentFvName != NULL) { + ParentFvNameValue = AllocateCopyPool (sizeof (EFI_GUID), ParentFvName); + ASSERT (ParentFvNameValue != NULL); + FvInfoPpi->ParentFvName = ParentFvNameValue; + } + if (ParentFileName != NULL) { + ParentFileNameValue = AllocateCopyPool (sizeof (EFI_GUID), ParentFileName); + ASSERT (ParentFileNameValue != NULL); + FvInfoPpi->ParentFileName = ParentFileNameValue; + } + + FvInfoPpiDescriptor = AllocatePool (sizeof (EFI_PEI_PPI_DESCRIPTOR)); + ASSERT (FvInfoPpiDescriptor != NULL); + + FvInfoPpiDescriptor->Guid = PpiGuid; + FvInfoPpiDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + FvInfoPpiDescriptor->Ppi = (VOID *) FvInfoPpi; + Status = PeiServicesInstallPpi (FvInfoPpiDescriptor); + ASSERT_EFI_ERROR (Status); + +} + +/** + Install a EFI_PEI_FIRMWARE_VOLUME_INFO_PPI instance so the PEI Core will be notified about a new firmware volume. + + This function allocates, initializes, and installs a new EFI_PEI_FIRMWARE_VOLUME_INFO_PPI using + the parameters passed in to initialize the fields of the EFI_PEI_FIRMWARE_VOLUME_INFO_PPI instance. + If the resources can not be allocated for EFI_PEI_FIRMWARE_VOLUME_INFO_PPI, then ASSERT(). + If the EFI_PEI_FIRMWARE_VOLUME_INFO_PPI can not be installed, then ASSERT(). + If NULL is specified for FvFormat, but FvInfo does not have the firmware file system 2 format, then ASSERT. + + @param FvFormat Unique identifier of the format of the memory-mapped + firmware volume. This parameter is optional and + may be NULL. If NULL is specified, the + EFI_FIRMWARE_FILE_SYSTEM2_GUID format is assumed. + @param FvInfo Points to a buffer which allows the + EFI_PEI_FIRMWARE_VOLUME_PPI to process the volume. + The format of this buffer is specific to the FvFormat. + For memory-mapped firmware volumes, this typically + points to the first byte of the firmware volume. + @param FvInfoSize The size, in bytes, of FvInfo. For memory-mapped + firmware volumes, this is typically the size of + the firmware volume. + @param ParentFvName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID name of the originating firmware + volume. Otherwise, this parameter must be NULL. + @param ParentFileName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID file name of the originating + firmware file. Otherwise, this parameter must be NULL. +**/ +VOID +EFIAPI +PeiServicesInstallFvInfoPpi ( + IN CONST EFI_GUID *FvFormat, OPTIONAL + IN CONST VOID *FvInfo, + IN UINT32 FvInfoSize, + IN CONST EFI_GUID *ParentFvName, OPTIONAL + IN CONST EFI_GUID *ParentFileName OPTIONAL + ) +{ + InternalPeiServicesInstallFvInfoPpi (TRUE, FvFormat, FvInfo, FvInfoSize, ParentFvName, ParentFileName, 0); +} + +/** + Install a EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI instance so the PEI Core will be notified about a new firmware volume. + + This function allocates, initializes, and installs a new EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI using + the parameters passed in to initialize the fields of the EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI instance. + If the resources can not be allocated for EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI, then ASSERT(). + If the EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI can not be installed, then ASSERT(). + If NULL is specified for FvFormat, but FvInfo does not have the firmware file system 2 format, then ASSERT. + + @param FvFormat Unique identifier of the format of the memory-mapped + firmware volume. This parameter is optional and + may be NULL. If NULL is specified, the + EFI_FIRMWARE_FILE_SYSTEM2_GUID format is assumed. + @param FvInfo Points to a buffer which allows the + EFI_PEI_FIRMWARE_VOLUME_PPI to process the volume. + The format of this buffer is specific to the FvFormat. + For memory-mapped firmware volumes, this typically + points to the first byte of the firmware volume. + @param FvInfoSize The size, in bytes, of FvInfo. For memory-mapped + firmware volumes, this is typically the size of + the firmware volume. + @param ParentFvName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID name of the originating firmware + volume. Otherwise, this parameter must be NULL. + @param ParentFileName If the new firmware volume originated from a file + in a different firmware volume, then this parameter + specifies the GUID file name of the originating + firmware file. Otherwise, this parameter must be NULL. + @param AuthenticationStatus Authentication Status +**/ +VOID +EFIAPI +PeiServicesInstallFvInfo2Ppi ( + IN CONST EFI_GUID *FvFormat, OPTIONAL + IN CONST VOID *FvInfo, + IN UINT32 FvInfoSize, + IN CONST EFI_GUID *ParentFvName, OPTIONAL + IN CONST EFI_GUID *ParentFileName, OPTIONAL + IN UINT32 AuthenticationStatus + ) +{ + InternalPeiServicesInstallFvInfoPpi (FALSE, FvFormat, FvInfo, FvInfoSize, ParentFvName, ParentFileName, AuthenticationStatus); +} + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. + +**/ +VOID +EFIAPI +PeiServicesResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + (*GetPeiServicesTablePointer())->ResetSystem2 (ResetType, ResetStatus, DataSize, ResetData); +} diff --git a/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf new file mode 100644 index 000000000..0a33ed86c --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf @@ -0,0 +1,43 @@ +## @file +# PEI Services Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiServicesLib + MODULE_UNI_FILE = PeiServicesLib.uni + FILE_GUID = a804239b-4155-446f-acc8-f0825d74908c + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiServicesLib|SEC PEIM PEI_CORE + PI_SPECIFICATION_VERSION = 0x0001000A + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiServicesLib.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PeiServicesTablePointerLib + MemoryAllocationLib + DebugLib + +[Guids] + gEfiFirmwareFileSystem2Guid ## SOMETIMES_PRODUCES ## GUID # FV File System Guid. + +[Ppis] + gEfiPeiFirmwareVolumeInfoPpiGuid ## SOMETIMES_PRODUCES + gEfiPeiFirmwareVolumeInfo2PpiGuid ## SOMETIMES_PRODUCES + diff --git a/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni new file mode 100644 index 000000000..8a7b71743 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni @@ -0,0 +1,16 @@ +// /** @file +// PEI Services Library implementation. +// +// PEI Services Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PEI Services Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "PEI Services Library implementation." + diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c new file mode 100644 index 000000000..831564d71 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c @@ -0,0 +1,110 @@ +/** @file + PEI Services Table Pointer Library. + + This library is used for PEIM which does executed from flash device directly but + executed in memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +CONST EFI_PEI_SERVICES **gPeiServices; + +/** + Caches a pointer PEI Services Table. + + Caches the pointer to the PEI Services Table specified by PeiServicesTablePointer + in a CPU specific manner as specified in the CPU binding section of the Platform Initialization + Pre-EFI Initialization Core Interface Specification. + + If PeiServicesTablePointer is NULL, then ASSERT(). + + @param PeiServicesTablePointer The address of PeiServices pointer. +**/ +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer + ) +{ + ASSERT (PeiServicesTablePointer != NULL); + gPeiServices = PeiServicesTablePointer; +} + +/** + Retrieves the cached value of the PEI Services Table pointer. + + Returns the cached value of the PEI Services Table pointer in a CPU specific manner + as specified in the CPU binding section of the Platform Initialization Pre-EFI + Initialization Core Interface Specification. + + If the cached PEI Services Table pointer is NULL, then ASSERT(). + + @return The pointer to PeiServices. + +**/ +CONST EFI_PEI_SERVICES ** +EFIAPI +GetPeiServicesTablePointer ( + VOID + ) +{ + ASSERT (gPeiServices != NULL); + return gPeiServices; +} + + +/** + The constructor function caches the pointer to PEI services. + + The constructor function caches the pointer to PEI services. + It will always return EFI_SUCCESS. + + @param FileHandle The handle of FFS header the loaded driver. + @param PeiServices The pointer to the PEI services. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PeiServicesTablePointerLibConstructor ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + gPeiServices = PeiServices; + return EFI_SUCCESS; +} + +/** + Perform CPU specific actions required to migrate the PEI Services Table + pointer from temporary RAM to permanent RAM. + + For IA32 CPUs, the PEI Services Table pointer is stored in the 4 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For X64 CPUs, the PEI Services Table pointer is stored in the 8 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For Itanium and ARM CPUs, a the PEI Services Table Pointer is stored in + a dedicated CPU register. This means that there is no memory storage + associated with storing the PEI Services Table pointer, so no additional + migration actions are required for Itanium or ARM CPUs. + +**/ +VOID +EFIAPI +MigratePeiServicesTablePointer ( + VOID + ) +{ + // + // PEI Services Table pointer is cached in the global variable. No additional + // migration actions are required. + // + return; +} diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf new file mode 100644 index 000000000..5c2a8e107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf @@ -0,0 +1,39 @@ +## @file +# Instance of PEI Services Table Pointer Library using global variable for the table pointer. +# +# PEI Services Table Pointer Library implementation that retrieves a pointer to the +# PEI Services Table from a global variable. Not available to modules that execute from +# read-only memory. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiServicesTablePointerLib + MODULE_UNI_FILE = PeiServicesTablePointerLib.uni + FILE_GUID = 1c747f6b-0a58-49ae-8ea3-0327a4fa10e3 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiServicesTablePointerLib|PEIM PEI_CORE SEC + + CONSTRUCTOR = PeiServicesTablePointerLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiServicesTablePointer.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni new file mode 100644 index 000000000..25a69a898 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni @@ -0,0 +1,18 @@ +// /** @file +// Instance of PEI Services Table Pointer Library using global variable for the table pointer. +// +// PEI Services Table Pointer Library implementation that retrieves a pointer to the +// PEI Services Table from a global variable. Not available to modules that execute from +// read-only memory. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PEI Services Table Pointer Library using global variable for the table pointer" + +#string STR_MODULE_DESCRIPTION #language en-US "The PEI Services Table Pointer Library implementation that retrieves a pointer to the PEI Services Table from a global variable. Not available to modules that execute from read-only memory." + diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c new file mode 100644 index 000000000..dac31c998 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c @@ -0,0 +1,125 @@ +/** @file + PEI Services Table Pointer Library for IA-32 and x64. + + According to PI specification, the peiservice pointer is stored prior at IDT + table in IA32 and x64 architecture. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +/** + Retrieves the cached value of the PEI Services Table pointer. + + Returns the cached value of the PEI Services Table pointer in a CPU specific manner + as specified in the CPU binding section of the Platform Initialization Pre-EFI + Initialization Core Interface Specification. + + If the cached PEI Services Table pointer is NULL, then ASSERT(). + + @return The pointer to PeiServices. + +**/ +CONST EFI_PEI_SERVICES ** +EFIAPI +GetPeiServicesTablePointer ( + VOID + ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + IA32_DESCRIPTOR Idtr; + + AsmReadIdtr (&Idtr); + PeiServices = (CONST EFI_PEI_SERVICES **) (*(UINTN*)(Idtr.Base - sizeof (UINTN))); + ASSERT (PeiServices != NULL); + return PeiServices; +} + +/** + Caches a pointer PEI Services Table. + + Caches the pointer to the PEI Services Table specified by PeiServicesTablePointer + in a CPU specific manner as specified in the CPU binding section of the Platform Initialization + Pre-EFI Initialization Core Interface Specification. + The function set the pointer of PEI services immediately preceding the IDT table + according to PI specification. + + If PeiServicesTablePointer is NULL, then ASSERT(). + + @param PeiServicesTablePointer The address of PeiServices pointer. +**/ +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer + ) +{ + IA32_DESCRIPTOR Idtr; + + ASSERT (PeiServicesTablePointer != NULL); + AsmReadIdtr (&Idtr); + (*(UINTN*)(Idtr.Base - sizeof (UINTN))) = (UINTN)PeiServicesTablePointer; +} + +/** + Perform CPU specific actions required to migrate the PEI Services Table + pointer from temporary RAM to permanent RAM. + + For IA32 CPUs, the PEI Services Table pointer is stored in the 4 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For X64 CPUs, the PEI Services Table pointer is stored in the 8 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For Itanium and ARM CPUs, a the PEI Services Table Pointer is stored in + a dedicated CPU register. This means that there is no memory storage + associated with storing the PEI Services Table pointer, so no additional + migration actions are required for Itanium or ARM CPUs. + + If The cached PEI Services Table pointer is NULL, then ASSERT(). + If the permanent memory is allocated failed, then ASSERT(). +**/ +VOID +EFIAPI +MigratePeiServicesTablePointer ( + VOID + ) +{ + EFI_STATUS Status; + IA32_DESCRIPTOR Idtr; + EFI_PHYSICAL_ADDRESS IdtBase; + CONST EFI_PEI_SERVICES **PeiServices; + + // + // Get PEI Services Table pointer + // + AsmReadIdtr (&Idtr); + PeiServices = (CONST EFI_PEI_SERVICES **) (*(UINTN*)(Idtr.Base - sizeof (UINTN))); + ASSERT (PeiServices != NULL); + // + // Allocate the permanent memory. + // + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesCode, + EFI_SIZE_TO_PAGES(Idtr.Limit + 1 + sizeof (UINTN)), + &IdtBase + ); + ASSERT_EFI_ERROR (Status); + // + // Idt table needs to be migrated into memory. + // + CopyMem ((VOID *) (UINTN) IdtBase, (VOID *) (Idtr.Base - sizeof (UINTN)), Idtr.Limit + 1 + sizeof (UINTN)); + Idtr.Base = (UINTN) IdtBase + sizeof (UINTN); + AsmWriteIdtr (&Idtr); + + return; +} + + diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf new file mode 100644 index 000000000..fcac6024a --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf @@ -0,0 +1,38 @@ +## @file +# Instance of PEI Services Table Pointer Library using IDT for the table pointer. +# +# PEI Services Table Pointer Library implementation that retrieves a pointer to the PEI +# Services Table from the IDT on IA-32 and x64. +# +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiServicesTablePointerLibIdt + MODULE_UNI_FILE = PeiServicesTablePointerLibIdt.uni + FILE_GUID = DED3F743-CE2C-4ba6-92A2-FFCE2A6D72D9 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiServicesTablePointerLib|PEIM PEI_CORE SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + +[Sources] + PeiServicesTablePointer.c + + +[LibraryClasses] + DebugLib + BaseLib + BaseMemoryLib diff --git a/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni new file mode 100644 index 000000000..5c22720c0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PEI Services Table Pointer Library using IDT for the table pointer. +// +// PEI Services Table Pointer Library implementation that retrieves a pointer to the PEI +// Services Table from the IDT on IA-32 and x64. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PEI Services Table Pointer Library using IDT for the table pointer" + +#string STR_MODULE_DESCRIPTION #language en-US "PEI Services Table Pointer Library implementation that retrieves a pointer to the PEI Services Table from the IDT on IA-32 and x64." + diff --git a/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h new file mode 100644 index 000000000..1eb6bbe92 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h @@ -0,0 +1,74 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#ifndef __INTERNAL_SMBUS_LIB_H_ +#define __INTERNAL_SMBUS_LIB_H_ + + +#include + +#include + +#include +#include +#include +#include + +// +// Declaration for internal functions +// + +/** + Gets Smbus PPIs. + + This internal function retrieves Smbus PPI from PPI database. + + @param VOID + + @return The pointer to Smbus PPI. + +**/ +EFI_PEI_SMBUS2_PPI * +InternalGetSmbusPpi ( + VOID + ); + +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol + instance that it will use to execute the SMBus transactions. + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will + do. The maximum number of bytes can be revision specific + and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave + device. Not all operations require this argument. The + length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c new file mode 100644 index 000000000..06a5f67e2 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c @@ -0,0 +1,89 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalSmbusLib.h" + +/** + Gets Smbus PPIs. + + This internal function retrieves Smbus PPI from PPI database. + + @param VOID + + @return The pointer to Smbus PPI. + +**/ +EFI_PEI_SMBUS2_PPI * +InternalGetSmbusPpi ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_SMBUS2_PPI *SmbusPpi; + + Status = PeiServicesLocatePpi (&gEfiPeiSmbus2PpiGuid, 0, NULL, (VOID **) &SmbusPpi); + ASSERT_EFI_ERROR (Status); + ASSERT (SmbusPpi != NULL); + + return SmbusPpi; +} + +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance + that it will use to execute the SMBus transactions. + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will + do. The maximum number of bytes can be revision specific + and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave + device. Not all operations require this argument. The + length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + EFI_PEI_SMBUS2_PPI *SmbusPpi; + RETURN_STATUS ReturnStatus; + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + SmbusPpi = InternalGetSmbusPpi (); + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + + ReturnStatus = SmbusPpi->Execute ( + SmbusPpi, + SmbusDeviceAddress, + SMBUS_LIB_COMMAND (SmBusAddress), + SmbusOperation, + SMBUS_LIB_PEC (SmBusAddress), + &Length, + Buffer + ); + if (Status != NULL) { + *Status = ReturnStatus; + } + + return Length; +} diff --git a/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf new file mode 100644 index 000000000..f581ef0da --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf @@ -0,0 +1,45 @@ +## @file +# SMBUS library that layers on top of the SMBUS2 PPI. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiSmbusLibSmbus2Ppi + MODULE_UNI_FILE = PeiSmbusLibSmbus2Ppi.uni + FILE_GUID = 2A1E1C92-AABA-4d62-AC40-F3A4C3387356 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmbusLib|PEIM SEC + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + SmbusLib.c + PeiSmbusLib.c + InternalSmbusLib.h + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + PeiServicesLib + DebugLib + +[Ppis] + gEfiPeiSmbus2PpiGuid ## CONSUMES + +[Depex.common.PEIM] + gEfiPeiSmbus2PpiGuid + diff --git a/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni new file mode 100644 index 000000000..0c92b777e --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni @@ -0,0 +1,16 @@ +// /** @file +// SMBUS library that layers on top of the SMBUS2 PPI. +// +// SMBUS library that layers on top of the SMBUS2 PPI. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMBUS library that layers on top of the SMBUS2 PPI" + +#string STR_MODULE_DESCRIPTION #language en-US "SMBUS library that layers on top of the SMBUS2 PPI." + diff --git a/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c new file mode 100644 index 000000000..d644583ba --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c @@ -0,0 +1,578 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "InternalSmbusLib.h" + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle + (host initiated), or bus errors (collisions). + RETURN_UNSUPPORTED: The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickRead, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_UNSUPPORTED:: The SMBus operation is not supported. + +**/ +VOID +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickWrite, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReceiveByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. Device + errors are a result of a transaction collision, illegal + command field, unclaimed cycle (host initiated), or bus + errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusSendByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusWriteByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadWord, SmBusAddress, 2, &Word, Status); + + return Word; +} + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Word = Value; + InternalSmBusExec (EfiSmbusWriteWord, SmBusAddress, 2, &Word, Status); + + return Value; +} + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusProcessCall, SmBusAddress, 2, &Value, Status); + + return Value; +} + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer The pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_SUCCESS: The SMBUS command was executed. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 0x20, Buffer, Status); +} + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + MBUS Command, SMBUS Data Length, and PEC. + @param Buffer The pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR: The checksum is not correct (PEC is incorrect) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Length = SMBUS_LIB_LENGTH (SmBusAddress); + return InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, Length, Buffer, Status); +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer The pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer The pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + RETURN_TIMEOUT: A timeout occurred while executing the + SMBUS command. + RETURN_DEVICE_ERROR: The request was not completed because + a failure reflected in the Host Status Register bit. + Device errors are a result of a transaction collision, + illegal command field, unclaimed cycle (host initiated), + or bus errors (collisions). + RETURN_CRC_ERROR The checksum is not correct. (PEC is incorrect.) + RETURN_UNSUPPORTED: The SMBus operation is not supported. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN Length; + + ASSERT (WriteBuffer != NULL); + ASSERT (ReadBuffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + Length = SMBUS_LIB_LENGTH (SmBusAddress); + // + // Assuming that ReadBuffer is large enough to save another memory copy. + // + ReadBuffer = CopyMem (ReadBuffer, WriteBuffer, Length); + return InternalSmBusExec (EfiSmbusBWBRProcessCall, SmBusAddress, Length, ReadBuffer, Status); +} diff --git a/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c new file mode 100644 index 000000000..524c2aaf7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c @@ -0,0 +1,75 @@ +/** @file + Entry point to a PEIM. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include + +/** + The entry point of PE/COFF Image for a PEIM. + + This function is the entry point for a PEIM. This function must call ProcessLibraryConstructorList() + and ProcessModuleEntryPointList(). The return value from ProcessModuleEntryPointList() is returned. + If _gPeimRevision is not zero and PeiServices->Hdr.Revision is less than _gPeimRevison, then ASSERT(). + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEIM executed normally. + @retval !EFI_SUCCESS The PEIM failed to execute normally. +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + if (_gPeimRevision != 0) { + // + // Make sure that the PEI spec revision of the platform is >= PEI spec revision of the driver + // + ASSERT ((*PeiServices)->Hdr.Revision >= _gPeimRevision); + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (FileHandle, PeiServices); + + // + // Call the driver entry point + // + return ProcessModuleEntryPointList (FileHandle, PeiServices); +} + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + This function is required to call _ModuleEntryPoint() passing in FileHandle and PeiServices. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEIM executed normally. + @retval !EFI_SUCCESS The PEIM failed to execute normally. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + return _ModuleEntryPoint (FileHandle, PeiServices); +} diff --git a/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf new file mode 100644 index 000000000..b4f6a7342 --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf @@ -0,0 +1,34 @@ +## @file +# Module entry point library for PEIM. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeimEntryPoint + MODULE_UNI_FILE = PeimEntryPoint.uni + FILE_GUID = fa177ff7-1fc7-458d-a358-d9d62ae61cec + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeimEntryPoint|PEIM + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeimEntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni new file mode 100644 index 000000000..bae3abaeb --- /dev/null +++ b/roms/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni @@ -0,0 +1,16 @@ +// /** @file +// Module entry point library for PEIM. +// +// Module entry point library for PEIM. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for PEIM" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for PEIM." + diff --git a/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf new file mode 100644 index 000000000..8da1d3854 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf @@ -0,0 +1,54 @@ +## @file +# Instance of Timer Library only using CPU resources. +# +# Timer Library that only uses CPU resources to provide calibrated delays +# on IA-32, x64, and IPF. +# Note: A driver of type DXE_RUNTIME_DRIVER and DXE_SMM_DRIVER can use this TimerLib +# in their initialization without any issues. They only have to be careful in +# the implementation of runtime services and SMI handlers. +# Because CPU Local APIC and ITC could be programmed by OS, it cannot be +# used by SMM drivers and runtime drivers, ACPI timer is recommended for SMM +# drivers and runtime drivers. +# +# Note that for IA-32 and x64, this library only supports xAPIC mode. If x2APIC +# support is desired, the SecPeiDxeTimerLibUefiCpu library can be used. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecPeiDxeTimerLibCpu + MODULE_UNI_FILE = SecPeiDxeTimerLibCpu.uni + FILE_GUID = b5a05743-9b71-489b-a0ed-a0eb3950d23b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32, Sources.X64] + X86TimerLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + +[LibraryClasses.IA32, LibraryClasses.X64] + PcdLib + IoLib + DebugLib + +[Pcd.IA32, Pcd.X64] + gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni new file mode 100644 index 000000000..62ff67785 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni @@ -0,0 +1,26 @@ +// /** @file +// Instance of Timer Library only using CPU resources. +// +// Timer Library that only uses CPU resources to provide calibrated delays +// on IA-32, x64, and IPF. +// Note: A driver of type DXE_RUNTIME_DRIVER and DXE_SMM_DRIVER can use this TimerLib +// in their initialization without any issues. They only have to be careful in +// the implementation of runtime services and SMI handlers. +// Because CPU Local APIC and ITC could be programmed by OS, it cannot be +// used by SMM drivers and runtime drivers, ACPI timer is recommended for SMM +// drivers and runtime drivers. +// +// Note that for IA-32 and x64, this library only supports xAPIC mode. If x2APIC +// support is desired, the SecPeiDxeTimerLibUefiCpu library can be used. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Timer Library only using CPU resources" + +#string STR_MODULE_DESCRIPTION #language en-US "This Timer Library only uses CPU resources to provide calibrated delays on IA-32, x64, and IPF. Note: A driver of types DXE_RUNTIME_DRIVER and DXE_SMM_DRIVER can use this TimerLib in their initialization without any issues. They only have to be careful in the implementation of runtime services and SMI handlers. Because CPU Local APIC and ITC could be programmed by the OS, it cannot be used by SMM drivers and runtime drivers, and ACPI timer is recommended for SMM drivers and runtime drivers. Note that for IA-32 and x64, this library only supports xAPIC mode. If x2APIC support is desired, the SecPeiDxeTimerLibUefiCpu library can be used." + diff --git a/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c new file mode 100644 index 000000000..50911fc55 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c @@ -0,0 +1,369 @@ +/** @file + Timer Library functions built upon local APIC on IA32/x64. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#define APIC_SVR 0x0f0 +#define APIC_LVTERR 0x370 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3e0 + +// +// The following array is used in calculating the frequency of local APIC +// timer. Refer to IA-32 developers' manual for more details. +// +GLOBAL_REMOVE_IF_UNREFERENCED +CONST UINT8 mTimerLibLocalApicDivisor[] = { + 0x02, 0x04, 0x08, 0x10, + 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x01, + 0x20, 0x40, 0x80, 0x01 +}; + +/** + Internal function to retrieve the base address of local APIC. + + This function will ASSERT if: + The local APIC is not globally enabled. + The local APIC is not working under XAPIC mode. + The local APIC is not software enabled. + + @return The base address of local APIC + +**/ +UINTN +EFIAPI +InternalX86GetApicBase ( + VOID + ) +{ + UINTN MsrValue; + UINTN ApicBase; + + MsrValue = (UINTN) AsmReadMsr64 (27); + ApicBase = MsrValue & 0xffffff000ULL; + + // + // Check the APIC Global Enable bit (bit 11) in IA32_APIC_BASE MSR. + // This bit will be 1, if local APIC is globally enabled. + // + ASSERT ((MsrValue & BIT11) != 0); + + // + // Check the APIC Extended Mode bit (bit 10) in IA32_APIC_BASE MSR. + // This bit will be 0, if local APIC is under XAPIC mode. + // + ASSERT ((MsrValue & BIT10) == 0); + + // + // Check the APIC Software Enable/Disable bit (bit 8) in Spurious-Interrupt + // Vector Register. + // This bit will be 1, if local APIC is software enabled. + // + ASSERT ((MmioRead32 (ApicBase + APIC_SVR) & BIT8) != 0); + + return ApicBase; +} + +/** + Internal function to return the frequency of the local APIC timer. + + @param ApicBase The base address of memory mapped registers of local APIC. + + @return The frequency of the timer in Hz. + +**/ +UINT32 +EFIAPI +InternalX86GetTimerFrequency ( + IN UINTN ApicBase + ) +{ + return + PcdGet32(PcdFSBClock) / + mTimerLibLocalApicDivisor[MmioBitFieldRead32 (ApicBase + APIC_TDCR, 0, 3)]; +} + +/** + Internal function to read the current tick counter of local APIC. + + @param ApicBase The base address of memory mapped registers of local APIC. + + @return The tick counter read. + +**/ +INT32 +EFIAPI +InternalX86GetTimerTick ( + IN UINTN ApicBase + ) +{ + return MmioRead32 (ApicBase + APIC_TMCCT); +} + +/** + Internal function to read the initial timer count of local APIC. + + @param ApicBase The base address of memory mapped registers of local APIC. + + @return The initial timer count read. + +**/ +UINT32 +InternalX86GetInitTimerCount ( + IN UINTN ApicBase + ) +{ + return MmioRead32 (ApicBase + APIC_TMICT); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + This function will ASSERT if the APIC timer intial count returned from + InternalX86GetInitTimerCount() is zero. + + @param ApicBase The base address of memory mapped registers of local APIC. + @param Delay A period of time to delay in ticks. + +**/ +VOID +EFIAPI +InternalX86Delay ( + IN UINTN ApicBase, + IN UINT32 Delay + ) +{ + INT32 Ticks; + UINT32 Times; + UINT32 InitCount; + UINT32 StartTick; + + // + // In case Delay is too larger, separate it into several small delay slot. + // Devided Delay by half value of Init Count is to avoid Delay close to + // the Init Count, timeout maybe missing if the time consuming between 2 + // GetApicTimerCurrentCount() invoking is larger than the time gap between + // Delay and the Init Count. + // + InitCount = InternalX86GetInitTimerCount (ApicBase); + ASSERT (InitCount != 0); + Times = Delay / (InitCount / 2); + Delay = Delay % (InitCount / 2); + + // + // Get Start Tick and do delay + // + StartTick = InternalX86GetTimerTick (ApicBase); + do { + // + // Wait until time out by Delay value + // + do { + CpuPause (); + // + // Get Ticks from Start to Current. + // + Ticks = StartTick - InternalX86GetTimerTick (ApicBase); + // + // Ticks < 0 means Timer wrap-arounds happens. + // + if (Ticks < 0) { + Ticks += InitCount; + } + } while ((UINT32)Ticks < Delay); + + // + // Update StartTick and Delay for next delay slot + // + StartTick -= (StartTick > Delay) ? Delay : (Delay - InitCount); + Delay = InitCount / 2; + } while (Times-- > 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return The value of MicroSeconds inputted. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + InternalX86Delay ( + ApicBase, + (UINT32)DivU64x32 ( + MultU64x64 ( + InternalX86GetTimerFrequency (ApicBase), + MicroSeconds + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return The value of NanoSeconds inputted. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + InternalX86Delay ( + ApicBase, + (UINT32)DivU64x32 ( + MultU64x64 ( + InternalX86GetTimerFrequency (ApicBase), + NanoSeconds + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + The counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return (UINT64)(UINT32)InternalX86GetTimerTick (InternalX86GetApicBase ()); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + + if (StartValue != NULL) { + *StartValue = (UINT64)InternalX86GetInitTimerCount (ApicBase); + } + + if (EndValue != NULL) { + *EndValue = 0; + } + + return (UINT64) InternalX86GetTimerFrequency (ApicBase); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN) Shift); + Frequency = RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} diff --git a/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c new file mode 100644 index 000000000..c2c6b8bc6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c @@ -0,0 +1,72 @@ +/** @file + NULL instance of SmiHandlerProfile Library. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + This function is called by SmmChildDispatcher module to report + a new SMI handler is registered, to SmmCore. + + @param HandlerGuid The GUID to identify the type of the handler. + For the SmmChildDispatch protocol, the HandlerGuid + must be the GUID of SmmChildDispatch protocol. + @param Handler The SMI handler. + @param CallerAddress The address of the module who registers the SMI handler. + @param Context The context of the SMI handler. + For the SmmChildDispatch protocol, the Context + must match the one defined for SmmChildDispatch protocol. + @param ContextSize The size of the context in bytes. + For the SmmChildDispatch protocol, the Context + must match the one defined for SmmChildDispatch protocol. + + @retval EFI_SUCCESS The information is recorded. + @retval EFI_UNSUPPORTED The feature is unsupported. + @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information. +**/ +EFI_STATUS +EFIAPI +SmiHandlerProfileRegisterHandler ( + IN EFI_GUID *HandlerGuid, + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN PHYSICAL_ADDRESS CallerAddress, + IN VOID *Context, OPTIONAL + IN UINTN ContextSize OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function is called by SmmChildDispatcher module to report + an existing SMI handler is unregistered, to SmmCore. + + @param HandlerGuid The GUID to identify the type of the handler. + For the SmmChildDispatch protocol, the HandlerGuid + must be the GUID of SmmChildDispatch protocol. + @param Handler The SMI handler. + @param Context The context of the SMI handler. + If it is NOT NULL, it will be used to check what is registered. + @param ContextSize The size of the context in bytes. + If Context is NOT NULL, it will be used to check what is registered. + + @retval EFI_SUCCESS The original record is removed. + @retval EFI_UNSUPPORTED The feature is unsupported. + @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler. +**/ +EFI_STATUS +EFIAPI +SmiHandlerProfileUnregisterHandler ( + IN EFI_GUID *HandlerGuid, + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN VOID *Context, OPTIONAL + IN UINTN ContextSize OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf new file mode 100644 index 000000000..caf9af899 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf @@ -0,0 +1,31 @@ +## @file +# NULL instance of SmiHandlerProfile Library. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmiHandlerProfileLibNull + MODULE_UNI_FILE = SmiHandlerProfileLibNull.uni + FILE_GUID = B43D1B52-6251-4E6F-82EC-A599A5EE94C1 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmiHandlerProfileLib|DXE_SMM_DRIVER SMM_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SmiHandlerProfileLibNull.c + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni new file mode 100644 index 000000000..82aa171bb --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// NULL instance of SmiHandlerProfile Library. +// +// NULL instance of SmiHandlerProfile Library. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "NULL instance of SmiHandlerProfile Library" + +#string STR_MODULE_DESCRIPTION #language en-US "NULL instance of SmiHandlerProfile Library." + diff --git a/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c new file mode 100644 index 000000000..31b1bb3ec --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c @@ -0,0 +1,325 @@ +/** @file + Instance of SMM IO check library. + + SMM IO check library library implementation. This library consumes GCD to collect all valid + IO space defined by a platform. + A platform may have its own SmmIoLib instance to exclude more IO space. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mSmmIoLibGcdMemSpace = NULL; +UINTN mSmmIoLibGcdMemNumberOfDesc = 0; + +EFI_PHYSICAL_ADDRESS mSmmIoLibInternalMaximumSupportMemAddress = 0; + +VOID *mSmmIoLibRegistrationEndOfDxe; +VOID *mSmmIoLibRegistrationReadyToLock; + +BOOLEAN mSmmIoLibReadyToLock = FALSE; + +/** + Calculate and save the maximum support address. + +**/ +VOID +SmmIoLibInternalCalculateMaximumSupportAddress ( + VOID + ) +{ + VOID *Hob; + UINT32 RegEax; + UINT8 MemPhysicalAddressBits; + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + MemPhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + MemPhysicalAddressBits = (UINT8) RegEax; + } else { + MemPhysicalAddressBits = 36; + } + } + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. + // + ASSERT (MemPhysicalAddressBits <= 52); + if (MemPhysicalAddressBits > 48) { + MemPhysicalAddressBits = 48; + } + + // + // Save the maximum support address in one global variable + // + mSmmIoLibInternalMaximumSupportMemAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, MemPhysicalAddressBits) - 1); + DEBUG ((DEBUG_INFO, "mSmmIoLibInternalMaximumSupportMemAddress = 0x%lx\n", mSmmIoLibInternalMaximumSupportMemAddress)); +} + +/** + This function check if the MMIO resource is valid per processor architecture and + valid per platform design. + + @param BaseAddress The MMIO start address to be checked. + @param Length The MMIO length to be checked. + @param Owner A GUID representing the owner of the resource. + This GUID may be used by producer to correlate the device ownership of the resource. + NULL means no specific owner. + + @retval TRUE This MMIO resource is valid per processor architecture and valid per platform design. + @retval FALSE This MMIO resource is not valid per processor architecture or valid per platform design. +**/ +BOOLEAN +EFIAPI +SmmIsMmioValid ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Owner OPTIONAL + ) +{ + UINTN Index; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc; + BOOLEAN InValidRegion; + + // + // Check override. + // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid. + // + if ((Length > mSmmIoLibInternalMaximumSupportMemAddress) || + (BaseAddress > mSmmIoLibInternalMaximumSupportMemAddress) || + ((Length != 0) && (BaseAddress > (mSmmIoLibInternalMaximumSupportMemAddress - (Length - 1)))) ) { + // + // Overflow happen + // + DEBUG (( + DEBUG_ERROR, + "SmmIsMmioValid: Overflow: BaseAddress (0x%lx) - Length (0x%lx), MaximumSupportMemAddress (0x%lx)\n", + BaseAddress, + Length, + mSmmIoLibInternalMaximumSupportMemAddress + )); + return FALSE; + } + + // + // Check override for valid MMIO region + // + if (mSmmIoLibReadyToLock) { + InValidRegion = FALSE; + for (Index = 0; Index < mSmmIoLibGcdMemNumberOfDesc; Index ++) { + Desc = &mSmmIoLibGcdMemSpace[Index]; + if ((Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && + (BaseAddress >= Desc->BaseAddress) && + ((BaseAddress + Length) <= (Desc->BaseAddress + Desc->Length))) { + InValidRegion = TRUE; + } + } + + if (!InValidRegion) { + DEBUG (( + DEBUG_ERROR, + "SmmIsMmioValid: Not in valid MMIO region: BaseAddress (0x%lx) - Length (0x%lx)\n", + BaseAddress, + Length + )); + return FALSE; + } + } + return TRUE; +} + +/** + Merge continuous entries whose type is EfiGcdMemoryTypeMemoryMappedIo. + + @param[in, out] GcdMemoryMap A pointer to the buffer in which firmware places + the current GCD memory map. + @param[in, out] NumberOfDescriptors A pointer to the number of the + GcdMemoryMap buffer. On input, this is the number of + the current GCD memory map. On output, + it is the number of new GCD memory map after merge. +**/ +STATIC +VOID +MergeGcdMmioEntry ( + IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMap, + IN OUT UINTN *NumberOfDescriptors + ) +{ + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMapEntry; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMapEnd; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *NewGcdMemoryMapEntry; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *NextGcdMemoryMapEntry; + + GcdMemoryMapEntry = GcdMemoryMap; + NewGcdMemoryMapEntry = GcdMemoryMap; + GcdMemoryMapEnd = (EFI_GCD_MEMORY_SPACE_DESCRIPTOR *) ((UINT8 *) GcdMemoryMap + (*NumberOfDescriptors) * sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); + while ((UINTN)GcdMemoryMapEntry < (UINTN)GcdMemoryMapEnd) { + CopyMem (NewGcdMemoryMapEntry, GcdMemoryMapEntry, sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); + NextGcdMemoryMapEntry = GcdMemoryMapEntry + 1; + + do { + if (((UINTN)NextGcdMemoryMapEntry < (UINTN)GcdMemoryMapEnd) && + (GcdMemoryMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && (NextGcdMemoryMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && + ((GcdMemoryMapEntry->BaseAddress + GcdMemoryMapEntry->Length) == NextGcdMemoryMapEntry->BaseAddress)) { + GcdMemoryMapEntry->Length += NextGcdMemoryMapEntry->Length; + if (NewGcdMemoryMapEntry != GcdMemoryMapEntry) { + NewGcdMemoryMapEntry->Length += NextGcdMemoryMapEntry->Length; + } + + NextGcdMemoryMapEntry = NextGcdMemoryMapEntry + 1; + continue; + } else { + GcdMemoryMapEntry = NextGcdMemoryMapEntry - 1; + break; + } + } while (TRUE); + + GcdMemoryMapEntry = GcdMemoryMapEntry + 1; + NewGcdMemoryMapEntry = NewGcdMemoryMapEntry + 1; + } + + *NumberOfDescriptors = ((UINTN)NewGcdMemoryMapEntry - (UINTN)GcdMemoryMap) / sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR); + + return ; +} + +/** + Notification for SMM EndOfDxe protocol. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. + @retval EFI_OUT_OF_RESOURCES No enough resources to save GCD MMIO map. +**/ +EFI_STATUS +EFIAPI +SmmIoLibInternalEndOfDxeNotify ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap; + EFI_STATUS Status; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap); + if (!EFI_ERROR (Status)) { + + MergeGcdMmioEntry (MemSpaceMap, &NumberOfDescriptors); + + mSmmIoLibGcdMemSpace = AllocateCopyPool (NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR), MemSpaceMap); + ASSERT (mSmmIoLibGcdMemSpace != NULL); + if (mSmmIoLibGcdMemSpace == NULL) { + gBS->FreePool (MemSpaceMap); + return EFI_OUT_OF_RESOURCES; + } + + mSmmIoLibGcdMemNumberOfDesc = NumberOfDescriptors; + gBS->FreePool (MemSpaceMap); + } + + return EFI_SUCCESS; +} + +/** + Notification for SMM ReadyToLock protocol. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. +**/ +EFI_STATUS +EFIAPI +SmmIoLibInternalReadyToLockNotify ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + mSmmIoLibReadyToLock = TRUE; + return EFI_SUCCESS; +} + +/** + The constructor function initializes the Smm IO library + + @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 +SmmIoLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Calculate and save maximum support address + // + SmmIoLibInternalCalculateMaximumSupportAddress (); + + // + // Register EndOfDxe to get GCD resource map + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, SmmIoLibInternalEndOfDxeNotify, &mSmmIoLibRegistrationEndOfDxe); + ASSERT_EFI_ERROR (Status); + + // + // Register ready to lock so that we can know when to check valid resource region + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, SmmIoLibInternalReadyToLockNotify, &mSmmIoLibRegistrationReadyToLock); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + The destructor function frees resource used in the Smm IO library + + @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 deconstructor always returns EFI_SUCCESS. +**/ +EFI_STATUS +EFIAPI +SmmIoLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, NULL, &mSmmIoLibRegistrationEndOfDxe); + gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, NULL, &mSmmIoLibRegistrationReadyToLock); + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf new file mode 100644 index 000000000..5f7356de5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf @@ -0,0 +1,47 @@ +## @file +# Instance of SMM IO check library. +# +# SMM IO check library library implementation. This library consumes GCD to collect all valid +# IO space defined by a platform. +# A platform may have its own SmmIoLib instance to exclude more IO space. +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmIoLib + MODULE_UNI_FILE = SmmIoLib.uni + FILE_GUID = F0F5A845-E3ED-4C6E-82D6-4ECE85DAC00F + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmIoLib|DXE_SMM_DRIVER SMM_CORE + CONSTRUCTOR = SmmIoLibConstructor + DESTRUCTOR = SmmIoLibDestructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmIoLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + SmmServicesTableLib + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + BaseMemoryLib + MemoryAllocationLib + HobLib + +[Protocols] + gEfiSmmReadyToLockProtocolGuid ## CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni new file mode 100644 index 000000000..d46bc0a7f --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni @@ -0,0 +1,18 @@ +// /** @file +// Instance of SMM IO check library. +// +// SMM IO check library library implementation. This library consumes GCD to collect all valid +// IO space defined by a platform. +// A platform may have its own SmmIoLib instance to exclude more IO space. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of SMM IO check library." + +#string STR_MODULE_DESCRIPTION #language en-US "SMM IO check library library implementation. This library consumes GCD to collect all valid IO space defined by a platform. A platform may have its own SmmIoLib instance to exclude more IO space." + diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c new file mode 100644 index 000000000..9262c88dc --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c @@ -0,0 +1,2306 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + The following IoLib instances share the same version of this file: + + BaseIoLibIntrinsic + DxeIoLibCpuIo + PeiIoLibCpuIo + SmmIoLibCpuIo +**/ + +#include "SmmCpuIoLibInternal.h" + +/** + Reads an 8-bit I/O port, performs a bitwise OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) | OrData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, (UINT8) (IoRead8 (Port) & AndData)); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (UINT8) ((IoRead8 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) | OrData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, (UINT16) (IoRead16 (Port) & AndData)); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (UINT16) ((IoRead16 (Port) & AndData) | OrData)); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) | OrData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, (UINT8) (MmioRead8 (Address) & AndData)); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (UINT8) ((MmioRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) | OrData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, (UINT16) (MmioRead16 (Address) & AndData)); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (UINT16) ((MmioRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c new file mode 100644 index 000000000..9163890b4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c @@ -0,0 +1,797 @@ +/** @file + I/O Library. + The implementation of I/O operation for this library instance + are based on EFI_CPU_IO_PROTOCOL. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SmmCpuIoLibInternal.h" + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all I/O read and write operations are serialized. + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI CPU I/O space. + +**/ +UINT64 +EFIAPI +IoReadWorker ( + IN UINTN Port, + IN EFI_SMM_IO_WIDTH Width + ) +{ + EFI_STATUS Status; + UINT64 Data; + + Status = gSmst->SmmIo.Io.Read (&gSmst->SmmIo, Width, Port, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all I/O read and write operations are serialized. + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return The parameter of Data. + +**/ +UINT64 +EFIAPI +IoWriteWorker ( + IN UINTN Port, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Data + ) +{ + EFI_STATUS Status; + + Status = gSmst->SmmIo.Io.Write (&gSmst->SmmIo, Width, Port, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Reads memory-mapped registers in the EFI system memory space. + + Reads the MMIO registers specified by Address with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioReadWorker ( + IN UINTN Address, + IN EFI_SMM_IO_WIDTH Width + ) +{ + EFI_STATUS Status; + UINT64 Data; + + Status = gSmst->SmmIo.Mem.Read (&gSmst->SmmIo, Width, Address, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Writes memory-mapped registers in the EFI system memory space. + + Writes the MMIO registers specified by Address with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioWriteWorker ( + IN UINTN Address, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Data + ) +{ + EFI_STATUS Status; + + Status = gSmst->SmmIo.Mem.Write (&gSmst->SmmIo, Width, Address, 1, &Data); + ASSERT_EFI_ERROR (Status); + + return Data; +} + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + return (UINT8)IoReadWorker (Port, SMM_IO_UINT8); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + return (UINT8)IoWriteWorker (Port, SMM_IO_UINT8, Value); +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + return (UINT16)IoReadWorker (Port, SMM_IO_UINT16); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + return (UINT16)IoWriteWorker (Port, SMM_IO_UINT16, Value); +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + return (UINT32)IoReadWorker (Port, SMM_IO_UINT32); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + return (UINT32)IoWriteWorker (Port, SMM_IO_UINT32, Value); +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + return IoReadWorker (Port, SMM_IO_UINT64); +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If Port is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + // + // Make sure Port is aligned on a 64-bit boundary. + // + ASSERT ((Port & 7) == 0); + return IoWriteWorker (Port, SMM_IO_UINT64, Value); +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 *Buffer8; + + Buffer8 = (UINT8 *)Buffer; + while (Count-- > 0) { + *Buffer8++ = IoRead8 (Port); + } +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 *Buffer8; + + Buffer8 = (UINT8 *)Buffer; + while (Count-- > 0) { + IoWrite8 (Port, *Buffer8++); + } +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT16 *Buffer16; + + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + Buffer16 = (UINT16 *)Buffer; + while (Count-- > 0) { + *Buffer16++ = IoRead16 (Port); + } +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT16 *Buffer16; + + // + // Make sure Port is aligned on a 16-bit boundary. + // + ASSERT ((Port & 1) == 0); + Buffer16 = (UINT16 *)Buffer; + while (Count-- > 0) { + IoWrite16 (Port, *Buffer16++); + } +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT32 *Buffer32; + + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + Buffer32 = (UINT32 *)Buffer; + while (Count-- > 0) { + *Buffer32++ = IoRead32 (Port); + } +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT32 *Buffer32; + + // + // Make sure Port is aligned on a 32-bit boundary. + // + ASSERT ((Port & 3) == 0); + Buffer32 = (UINT32 *)Buffer; + while (Count-- > 0) { + IoWrite32 (Port, *Buffer32++); + } +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + return (UINT8)MmioReadWorker (Address, SMM_IO_UINT8); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return (UINT8)MmioWriteWorker (Address, SMM_IO_UINT8, Value); +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + return (UINT16)MmioReadWorker (Address, SMM_IO_UINT16); +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + // + // Make sure Address is aligned on a 16-bit boundary. + // + ASSERT ((Address & 1) == 0); + return (UINT16)MmioWriteWorker (Address, SMM_IO_UINT16, Value); +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + return (UINT32)MmioReadWorker (Address, SMM_IO_UINT32); +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + // + // Make sure Address is aligned on a 32-bit boundary. + // + ASSERT ((Address & 3) == 0); + return (UINT32)MmioWriteWorker (Address, SMM_IO_UINT32, Value); +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & 7) == 0); + return (UINT64)MmioReadWorker (Address, SMM_IO_UINT64); +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If Address is not aligned on a 64-bit boundary, then ASSERT(). + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + // + // Make sure Address is aligned on a 64-bit boundary. + // + ASSERT ((Address & 7) == 0); + return (UINT64)MmioWriteWorker (Address, SMM_IO_UINT64, Value); +} diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c new file mode 100644 index 000000000..2436c0524 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c @@ -0,0 +1,411 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SmmCpuIoLibInternal.h" + +/** + Copy data from MMIO region to system memory by using 8-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 8-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ) +{ + UINT8 *ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = Buffer; + + while (Length-- > 0) { + *(Buffer++) = MmioRead8 (StartAddress++); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 16-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 16-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 32-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 32-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from MMIO region to system memory by using 64-bit access. + + Copy data from MMIO region specified by starting address StartAddress + to system memory specified by Buffer by using 64-bit access. The total + number of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied from. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = Buffer; + + while (Length > 0) { + *(Buffer++) = MmioRead64 (StartAddress); + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 8-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 8-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the + data to write. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioWriteBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT8 *Buffer + ) +{ + VOID* ReturnBuffer; + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ReturnBuffer = (UINT8 *) Buffer; + + while (Length-- > 0) { + MmioWrite8 (StartAddress++, *(Buffer++)); + } + + return ReturnBuffer; + +} + +/** + Copy data from system memory to MMIO region by using 16-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 16-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 16-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the + data to write. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioWriteBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT16 *Buffer + ) +{ + UINT16 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT16) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0); + + ReturnBuffer = (UINT16 *) Buffer; + + while (Length > 0) { + MmioWrite16 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT16); + Length -= sizeof (UINT16); + } + + return ReturnBuffer; +} + + +/** + Copy data from system memory to MMIO region by using 32-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 32-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 32-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the + data to write. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioWriteBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT32 *Buffer + ) +{ + UINT32 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT32) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT32) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT32) - 1)) == 0); + + ReturnBuffer = (UINT32 *) Buffer; + + while (Length > 0) { + MmioWrite32 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT32); + Length -= sizeof (UINT32); + } + + return ReturnBuffer; +} + +/** + Copy data from system memory to MMIO region by using 64-bit access. + + Copy data from system memory specified by Buffer to MMIO region specified + by starting address StartAddress by using 64-bit access. The total number + of byte to be copied is specified by Length. Buffer is returned. + + If StartAddress is not aligned on a 64-bit boundary, then ASSERT(). + + If Length is greater than (MAX_ADDRESS - StartAddress + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS -Buffer + 1), then ASSERT(). + + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + + @param StartAddress The starting address for the MMIO region to be copied to. + @param Length The size in bytes of the copy. + @param Buffer The pointer to a system memory buffer containing the + data to write. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioWriteBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + IN CONST UINT64 *Buffer + ) +{ + UINT64 *ReturnBuffer; + + ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); + + ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); + + ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); + ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); + + ReturnBuffer = (UINT64 *) Buffer; + + while (Length > 0) { + MmioWrite64 (StartAddress, *(Buffer++)); + + StartAddress += sizeof (UINT64); + Length -= sizeof (UINT64); + } + + return ReturnBuffer; +} + diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h new file mode 100644 index 000000000..51953e30f --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h @@ -0,0 +1,112 @@ +/** @file + Internal include file of SMM CPU IO Library. + It includes all necessary protocol/library class's header file + for implementation of IoLib library instance. It is included + all source code of this library instance. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SMM_CPUIO_LIB_INTERNAL_H_ +#define _SMM_CPUIO_LIB_INTERNAL_H_ + +#include +#include +#include +#include +#include +#include +#include + + +/** + Reads registers in the EFI CPU I/O space. + + Reads the I/O port specified by Port with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all I/O read and write operations are serialized. + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI CPU I/O space. + +**/ +UINT64 +EFIAPI +IoReadWorker ( + IN UINTN Port, + IN EFI_SMM_IO_WIDTH Width + ); + +/** + Writes registers in the EFI CPU I/O space. + + Writes the I/O port specified by Port with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all I/O read and write operations are serialized. + + @param Port The base address of the I/O operation. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return The parameter of Data. + +**/ +UINT64 +EFIAPI +IoWriteWorker ( + IN UINTN Port, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Data + ); + +/** + Reads memory-mapped registers in the EFI system memory space. + + Reads the MMIO registers specified by Address with registers width specified by Width. + The read value is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioReadWorker ( + IN UINTN Address, + IN EFI_SMM_IO_WIDTH Width + ); + +/** + Writes memory-mapped registers in the EFI system memory space. + + Writes the MMIO registers specified by Address with registers width and value specified by Width + and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). + This function must guarantee that all MMIO read and write operations are serialized. + + @param Address The MMIO register to read. + The caller is responsible for aligning the Address if required. + @param Width The width of the I/O operation. + @param Data The value to write to the I/O port. + + @return Data read from registers in the EFI system memory space. + +**/ +UINT64 +EFIAPI +MmioWriteWorker ( + IN UINTN Address, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Data + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf new file mode 100644 index 000000000..6fe40e473 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf @@ -0,0 +1,44 @@ +## @file +# SMM Instance of I/O Library using SMM CPU I/O 2 Protocol. +# +# I/O Library SMM implementation that uses SMM CPU I/O 2 Protocol for I/O +# and MMIO operations. +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmIoLibSmmCpuIo2 + MODULE_UNI_FILE = SmmIoLibSmmCpuIo2.uni + FILE_GUID = DEEEA15E-4A77-4513-BA75-71D26FEF78A1 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoLib|DXE_SMM_DRIVER SMM_CORE + PI_SPECIFICATION_VERSION = 0x0001000A + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + IoLibMmioBuffer.c + SmmCpuIoLibInternal.h + IoHighLevel.c + IoLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + SmmServicesTableLib + +[Depex.common.DXE_SMM_DRIVER] + gEfiSmmCpuIo2ProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni new file mode 100644 index 000000000..3ad4b16be --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni @@ -0,0 +1,17 @@ +// /** @file +// SMM Instance of I/O Library using SMM CPU I/O 2 Protocol. +// +// I/O Library SMM implementation that uses SMM CPU I/O 2 Protocol for I/O +// and MMIO operations. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "The SMM Instance of I/O Library using SMM CPU I/O 2 Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "This I/O Library SMM implementation uses the SMM CPU I/O 2 Protocol for I/O and MMIO operations." + diff --git a/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c new file mode 100644 index 000000000..28c4f2fda --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c @@ -0,0 +1,97 @@ +/** @file + NULL instance of SMM Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Triggers an SMI at boot time. + + This function triggers a software SMM interrupt at boot time. + +**/ +VOID +EFIAPI +TriggerBootServiceSoftwareSmi ( + VOID + ) +{ + return; +} + + +/** + Triggers an SMI at run time. + + This function triggers a software SMM interrupt at run time. + +**/ +VOID +EFIAPI +TriggerRuntimeSoftwareSmi ( + VOID + ) +{ + return; +} + + + +/** + Test if a boot time software SMI happened. + + This function tests if a software SMM interrupt happened. If a software SMM + interrupt happened and it was triggered at boot time, it returns TRUE. Otherwise, + it returns FALSE. + + @retval TRUE A software SMI triggered at boot time happened. + @retval FALSE No software SMI happened or the software SMI was triggered at run time. + +**/ +BOOLEAN +EFIAPI +IsBootServiceSoftwareSmi ( + VOID + ) +{ + return FALSE; +} + + +/** + Test if a run time software SMI happened. + + This function tests if a software SMM interrupt happened. If a software SMM + interrupt happened and it was triggered at run time, it returns TRUE. Otherwise, + it returns FALSE. + + @retval TRUE A software SMI triggered at run time happened. + @retval FALSE No software SMI happened or the software SMI was triggered at boot time. + +**/ +BOOLEAN +EFIAPI +IsRuntimeSoftwareSmi ( + VOID + ) +{ + return FALSE; +} + +/** + Clear APM SMI Status Bit; Set the EOS bit. + +**/ +VOID +EFIAPI +ClearSmi ( + VOID + ) +{ + return; +} diff --git a/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf new file mode 100644 index 000000000..0b7e491db --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf @@ -0,0 +1,32 @@ +## @file +# NULL instance of SMM Library. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmLibNull + MODULE_UNI_FILE = SmmLibNull.uni + FILE_GUID = DDADFC93-FBC5-4389-B20F-EC99E4A6AE52 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SmmLibNull.c + + +[Packages] + MdePkg/MdePkg.dec + diff --git a/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni new file mode 100644 index 000000000..0468efa3c --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni @@ -0,0 +1,16 @@ +// /** @file +// NULL instance of SMM Library. +// +// NULL instance of SMM Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "NULL instance of SMM Library" + +#string STR_MODULE_DESCRIPTION #language en-US "NULL instance of SMM Library." + diff --git a/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c new file mode 100644 index 000000000..63a4ff7a9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c @@ -0,0 +1,652 @@ +/** @file + Instance of SMM memory check library. + + SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL + to get SMRAM information. In order to use this library instance, the platform should produce + all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core + and SMM driver) and/or specific dedicated hardware. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// attributes for reserved memory before it is promoted to system memory +// +#define EFI_MEMORY_PRESENT 0x0100000000000000ULL +#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL +#define EFI_MEMORY_TESTED 0x0400000000000000ULL + +EFI_SMRAM_DESCRIPTOR *mSmmMemLibInternalSmramRanges; +UINTN mSmmMemLibInternalSmramCount; + +// +// Maximum support address used to check input buffer +// +EFI_PHYSICAL_ADDRESS mSmmMemLibInternalMaximumSupportAddress = 0; + +UINTN mMemoryMapEntryCount; +EFI_MEMORY_DESCRIPTOR *mMemoryMap; +UINTN mDescriptorSize; + +EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mSmmMemLibGcdMemSpace = NULL; +UINTN mSmmMemLibGcdMemNumberOfDesc = 0; + +EFI_MEMORY_ATTRIBUTES_TABLE *mSmmMemLibMemoryAttributesTable = NULL; + +VOID *mRegistrationEndOfDxe; +VOID *mRegistrationReadyToLock; + +BOOLEAN mSmmMemLibSmmReadyToLock = FALSE; + +/** + Calculate and save the maximum support address. + +**/ +VOID +SmmMemLibInternalCalculateMaximumSupportAddress ( + VOID + ) +{ + VOID *Hob; + UINT32 RegEax; + UINT8 PhysicalAddressBits; + + // + // 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; + } + + // + // Save the maximum support address in one global variable + // + mSmmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); + DEBUG ((EFI_D_INFO, "mSmmMemLibInternalMaximumSupportAddress = 0x%lx\n", mSmmMemLibInternalMaximumSupportAddress)); +} + +/** + This function check if the buffer is valid per processor architecture and not overlap with SMRAM. + + @param Buffer The buffer start address to be checked. + @param Length The buffer length to be checked. + + @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM. + @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM. +**/ +BOOLEAN +EFIAPI +SmmIsBufferOutsideSmmValid ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length + ) +{ + UINTN Index; + + // + // Check override. + // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid. + // + if ((Length > mSmmMemLibInternalMaximumSupportAddress) || + (Buffer > mSmmMemLibInternalMaximumSupportAddress) || + ((Length != 0) && (Buffer > (mSmmMemLibInternalMaximumSupportAddress - (Length - 1)))) ) { + // + // Overflow happen + // + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n", + Buffer, + Length, + mSmmMemLibInternalMaximumSupportAddress + )); + return FALSE; + } + + for (Index = 0; Index < mSmmMemLibInternalSmramCount; Index ++) { + if (((Buffer >= mSmmMemLibInternalSmramRanges[Index].CpuStart) && (Buffer < mSmmMemLibInternalSmramRanges[Index].CpuStart + mSmmMemLibInternalSmramRanges[Index].PhysicalSize)) || + ((mSmmMemLibInternalSmramRanges[Index].CpuStart >= Buffer) && (mSmmMemLibInternalSmramRanges[Index].CpuStart < Buffer + Length))) { + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ", + Buffer, + Length + )); + DEBUG (( + EFI_D_ERROR, + "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n", + mSmmMemLibInternalSmramRanges[Index].CpuStart, + mSmmMemLibInternalSmramRanges[Index].PhysicalSize + )); + return FALSE; + } + } + + // + // Check override for Valid Communication Region + // + if (mSmmMemLibSmmReadyToLock) { + EFI_MEMORY_DESCRIPTOR *MemoryMap; + BOOLEAN InValidCommunicationRegion; + + InValidCommunicationRegion = FALSE; + MemoryMap = mMemoryMap; + for (Index = 0; Index < mMemoryMapEntryCount; Index++) { + if ((Buffer >= MemoryMap->PhysicalStart) && + (Buffer + Length <= MemoryMap->PhysicalStart + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) { + InValidCommunicationRegion = TRUE; + } + MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mDescriptorSize); + } + + if (!InValidCommunicationRegion) { + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)\n", + Buffer, + Length + )); + return FALSE; + } + + // + // Check untested memory as invalid communication buffer. + // + for (Index = 0; Index < mSmmMemLibGcdMemNumberOfDesc; Index++) { + if (((Buffer >= mSmmMemLibGcdMemSpace[Index].BaseAddress) && (Buffer < mSmmMemLibGcdMemSpace[Index].BaseAddress + mSmmMemLibGcdMemSpace[Index].Length)) || + ((mSmmMemLibGcdMemSpace[Index].BaseAddress >= Buffer) && (mSmmMemLibGcdMemSpace[Index].BaseAddress < Buffer + Length))) { + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: In Untested Memory Region: Buffer (0x%lx) - Length (0x%lx)\n", + Buffer, + Length + )); + return FALSE; + } + } + + // + // Check UEFI runtime memory with EFI_MEMORY_RO as invalid communication buffer. + // + if (mSmmMemLibMemoryAttributesTable != NULL) { + EFI_MEMORY_DESCRIPTOR *Entry; + + Entry = (EFI_MEMORY_DESCRIPTOR *)(mSmmMemLibMemoryAttributesTable + 1); + for (Index = 0; Index < mSmmMemLibMemoryAttributesTable->NumberOfEntries; Index++) { + if (Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) { + if ((Entry->Attribute & EFI_MEMORY_RO) != 0) { + if (((Buffer >= Entry->PhysicalStart) && (Buffer < Entry->PhysicalStart + LShiftU64 (Entry->NumberOfPages, EFI_PAGE_SHIFT))) || + ((Entry->PhysicalStart >= Buffer) && (Entry->PhysicalStart < Buffer + Length))) { + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: In RuntimeCode Region: Buffer (0x%lx) - Length (0x%lx)\n", + Buffer, + Length + )); + return FALSE; + } + } + } + Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mSmmMemLibMemoryAttributesTable->DescriptorSize); + } + } + } + return TRUE; +} + +/** + Copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if source buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it return EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMemToSmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMemToSmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (SMRAM) to a destination buffer (NON-SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if destination buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMemFromSmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMemFromSmram: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (NON-SMRAM) to a destination buffer (NON-SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if source buffer and destination buffer are valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Fills a target buffer (NON-SMRAM) with a byte value. + + This function fills a target buffer (non-SMRAM) with a byte value. + It checks if target buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it fills memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is set. + +**/ +EFI_STATUS +EFIAPI +SmmSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length)); + return EFI_SECURITY_VIOLATION; + } + SetMem (Buffer, Length, Value); + return EFI_SUCCESS; +} + +/** + Get GCD memory map. + Only record untested memory as invalid communication buffer. +**/ +VOID +SmmMemLibInternalGetGcdMemoryMap ( + VOID + ) +{ + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap; + EFI_STATUS Status; + UINTN Index; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap); + if (EFI_ERROR (Status)) { + return ; + } + + mSmmMemLibGcdMemNumberOfDesc = 0; + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved && + (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED) + ) { + mSmmMemLibGcdMemNumberOfDesc++; + } + } + + mSmmMemLibGcdMemSpace = AllocateZeroPool (mSmmMemLibGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); + ASSERT (mSmmMemLibGcdMemSpace != NULL); + if (mSmmMemLibGcdMemSpace == NULL) { + mSmmMemLibGcdMemNumberOfDesc = 0; + gBS->FreePool (MemSpaceMap); + return ; + } + + mSmmMemLibGcdMemNumberOfDesc = 0; + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved && + (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED) + ) { + CopyMem ( + &mSmmMemLibGcdMemSpace[mSmmMemLibGcdMemNumberOfDesc], + &MemSpaceMap[Index], + sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR) + ); + mSmmMemLibGcdMemNumberOfDesc++; + } + } + + gBS->FreePool (MemSpaceMap); +} + +/** + Get UEFI MemoryAttributesTable. +**/ +VOID +SmmMemLibInternalGetUefiMemoryAttributesTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; + UINTN MemoryAttributesTableSize; + + Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); + if (!EFI_ERROR (Status) && (MemoryAttributesTable != NULL)) { + MemoryAttributesTableSize = sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + MemoryAttributesTable->DescriptorSize * MemoryAttributesTable->NumberOfEntries; + mSmmMemLibMemoryAttributesTable = AllocateCopyPool (MemoryAttributesTableSize, MemoryAttributesTable); + ASSERT (mSmmMemLibMemoryAttributesTable != NULL); + } +} + +/** + Notification for SMM EndOfDxe protocol. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. +**/ +EFI_STATUS +EFIAPI +SmmLibInternalEndOfDxeNotify ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + UINTN MapKey; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapStart; + EFI_MEMORY_DESCRIPTOR *SmmMemoryMapStart; + UINTN MemoryMapEntryCount; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINTN Index; + + MemoryMapSize = 0; + MemoryMap = NULL; + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + do { + Status = gBS->AllocatePool (EfiBootServicesData, MemoryMapSize, (VOID **)&MemoryMap); + ASSERT (MemoryMap != NULL); + + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (MemoryMap); + } + } while (Status == EFI_BUFFER_TOO_SMALL); + + // + // Get Count + // + mDescriptorSize = DescriptorSize; + MemoryMapEntryCount = MemoryMapSize/DescriptorSize; + MemoryMapStart = MemoryMap; + mMemoryMapEntryCount = 0; + for (Index = 0; Index < MemoryMapEntryCount; Index++) { + switch (MemoryMap->Type) { + case EfiReservedMemoryType: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiACPIMemoryNVS: + mMemoryMapEntryCount++; + break; + } + MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize); + } + MemoryMap = MemoryMapStart; + + // + // Get Data + // + mMemoryMap = AllocatePool (mMemoryMapEntryCount*DescriptorSize); + ASSERT (mMemoryMap != NULL); + SmmMemoryMapStart = mMemoryMap; + for (Index = 0; Index < MemoryMapEntryCount; Index++) { + switch (MemoryMap->Type) { + case EfiReservedMemoryType: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiACPIMemoryNVS: + CopyMem (mMemoryMap, MemoryMap, DescriptorSize); + mMemoryMap = NEXT_MEMORY_DESCRIPTOR(mMemoryMap, DescriptorSize); + break; + } + MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize); + } + mMemoryMap = SmmMemoryMapStart; + MemoryMap = MemoryMapStart; + + gBS->FreePool (MemoryMap); + + // + // Get additional information from GCD memory map. + // + SmmMemLibInternalGetGcdMemoryMap (); + + // + // Get UEFI memory attributes table. + // + SmmMemLibInternalGetUefiMemoryAttributesTable (); + + return EFI_SUCCESS; +} + +/** + Notification for SMM ReadyToLock protocol. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. +**/ +EFI_STATUS +EFIAPI +SmmLibInternalReadyToLockNotify ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + mSmmMemLibSmmReadyToLock = TRUE; + return EFI_SUCCESS; +} +/** + The constructor function initializes the Smm Mem library + + @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 +SmmMemLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + UINTN Size; + + // + // Get SMRAM information + // + Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess); + ASSERT_EFI_ERROR (Status); + + Size = 0; + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + mSmmMemLibInternalSmramRanges = AllocatePool (Size); + ASSERT (mSmmMemLibInternalSmramRanges != NULL); + + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmmMemLibInternalSmramRanges); + ASSERT_EFI_ERROR (Status); + + mSmmMemLibInternalSmramCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + // + // Calculate and save maximum support address + // + SmmMemLibInternalCalculateMaximumSupportAddress (); + + // + // Register EndOfDxe to get UEFI memory map + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, SmmLibInternalEndOfDxeNotify, &mRegistrationEndOfDxe); + ASSERT_EFI_ERROR (Status); + + // + // Register ready to lock so that we can know when to check valid SMRAM region + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, SmmLibInternalReadyToLockNotify, &mRegistrationReadyToLock); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + The destructor function frees resource used in the Smm Mem library + + @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 deconstructor always returns EFI_SUCCESS. +**/ +EFI_STATUS +EFIAPI +SmmMemLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FreePool (mSmmMemLibInternalSmramRanges); + + gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, NULL, &mRegistrationEndOfDxe); + gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, NULL, &mRegistrationReadyToLock); + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf new file mode 100644 index 000000000..bc30057d7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf @@ -0,0 +1,56 @@ +## @file +# Instance of SMM memory check library. +# +# SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL +# to get SMRAM information. In order to use this library instance, the platform should produce +# all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core +# and SMM driver) and/or specific dedicated hardware. +# +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmMemLib + MODULE_UNI_FILE = SmmMemLib.uni + FILE_GUID = 7F23F839-C81C-4B89-8132-69746FCBCE52 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmMemLib|DXE_SMM_DRIVER SMM_CORE + CONSTRUCTOR = SmmMemLibConstructor + DESTRUCTOR = SmmMemLibDestructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmMemLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + SmmServicesTableLib + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + BaseMemoryLib + HobLib + MemoryAllocationLib + UefiLib + +[Protocols] + gEfiSmmAccess2ProtocolGuid ## CONSUMES + gEfiSmmReadyToLockProtocolGuid ## CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## CONSUMES + +[Guids] + gEfiMemoryAttributesTableGuid ## CONSUMES ## SystemTable + +[Depex] + gEfiSmmAccess2ProtocolGuid diff --git a/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni new file mode 100644 index 000000000..f1d678344 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni @@ -0,0 +1,19 @@ +// /** @file +// SMM memory check library. +// +// SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL +// to get SMRAM information. In order to use this library instance, the platform should produce +// all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core +// and SMM driver) and/or specific dedicated hardware. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMM memory check library" + +#string STR_MODULE_DESCRIPTION #language en-US "SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL to get SMRAM information. In order to use this library instance, the platform should produce all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core and SMM driver) and/or specific dedicated hardware." + diff --git a/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 000000000..c0247a3a4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,976 @@ +/** @file + Support routines for memory allocation routines based + on SMM Services Table services for SMM phase drivers. + + The PI System Management Mode Core Interface Specification only allows the use + of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory + allocations through the SMM Services Table as the SMRAM space should be + reserved after BDS phase. The functions in the Memory Allocation Library use + EfiBootServicesData as the default memory allocation type. For this SMM + specific instance of the Memory Allocation Library, EfiRuntimeServicesData + is used as the default memory type for all allocations. In addition, + allocation for the Reserved memory types are not supported and will always + return NULL. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +EFI_SMRAM_DESCRIPTOR *mSmramRanges; +UINTN mSmramRangeCount; + +/** + The constructor function caches SMRAM ranges that are present in the system. + + It will ASSERT() if SMM Access2 Protocol doesn't exist. + It will ASSERT() if SMRAM ranges can't be got. + It will ASSERT() if Resource can't be allocated for cache SMRAM range. + 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 +SmmMemoryAllocationLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + UINTN Size; + + // + // Locate SMM Access2 Protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmAccess2ProtocolGuid, + NULL, + (VOID **)&SmmAccess + ); + ASSERT_EFI_ERROR (Status); + + // + // Get SMRAM range information + // + Size = 0; + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size); + ASSERT (mSmramRanges != NULL); + + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges); + ASSERT_EFI_ERROR (Status); + + mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + return EFI_SUCCESS; +} + +/** + If SMM driver exits with an error, it must call this routine + to free the allocated resource before the exiting. + + @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 deconstructor always returns EFI_SUCCESS. +**/ +EFI_STATUS +EFIAPI +SmmMemoryAllocationLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FreePool (mSmramRanges); + + return EFI_SUCCESS; +} + +/** + Check whether the start address of buffer is within any of the SMRAM ranges. + + @param[in] Buffer The pointer to the buffer to be checked. + + @retval TRUE The buffer is in SMRAM ranges. + @retval FALSE The buffer is out of SMRAM ranges. +**/ +BOOLEAN +EFIAPI +BufferInSmram ( + IN VOID *Buffer + ) +{ + UINTN Index; + + for (Index = 0; Index < mSmramRangeCount; Index ++) { + if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) && + ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) { + return TRUE; + } + } + + return FALSE; +} + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer + to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If + Pages is 0, then NULL is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer + to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If + Pages is 0, then NULL is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. If there is not enough memory remaining + to satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. If there is not enough memory remaining + to satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. + Buffer must have been allocated on a previous call to the page allocation services + of the Memory Allocation Library. If it is not possible to free allocated pages, + then this function will perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. + // So, gSmst->SmmFreePages() service is used to free it. + // + Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. + // So, gBS->FreePages() service is used to free it. + // + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gSmst->SmmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gSmst->SmmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by + Buffer. Buffer must have been allocated on a previous call to the aligned page + allocation services of the Memory Allocation Library. If it is not possible to + free allocated pages, then this function will perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the + Memory Allocation Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. + // So, gSmst->SmmFreePages() service is used to free it. + // + Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. + // So, gBS->FreePages() service is used to free it. + // + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return NULL; +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize + and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize + and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return NULL; +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation + functions in the Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a + previous call to the pool allocation services of the Memory Allocation Library. + If it is not possible to free pool resources, then this function will perform + no actions. + + If Buffer was not allocated with a pool allocation function in the Memory + Allocation Library, then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service. + // So, gSmst->SmmFreePool() service is used to free it. + // + Status = gSmst->SmmFreePool (Buffer); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service. + // So, gBS->FreePool() service is used to free it. + // + Status = gBS->FreePool (Buffer); + } + ASSERT_EFI_ERROR (Status); +} diff --git a/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf new file mode 100644 index 000000000..9f0ecbf66 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf @@ -0,0 +1,45 @@ +## @file +# Instance of Memory Allocation Library using SMM Services Table. +# +# Memory Allocation Library that uses services from the SMM Services Table to +# allocate and free memory. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmMemoryAllocationLib + MODULE_UNI_FILE = SmmMemoryAllocationLib.uni + FILE_GUID = 4DF30A5D-D5B0-4f85-80ED-6B16CD343C8E + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + LIBRARY_CLASS = MemoryAllocationLib|DXE_SMM_DRIVER + CONSTRUCTOR = SmmMemoryAllocationLibConstructor + DESTRUCTOR = SmmMemoryAllocationLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemoryAllocationLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + SmmServicesTableLib + UefiBootServicesTableLib + +[Protocols] + gEfiSmmAccess2ProtocolGuid ## CONSUMES + +[Depex] + gEfiSmmAccess2ProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni new file mode 100644 index 000000000..6e0c19368 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Memory Allocation Library using SMM Services Table. +// +// Memory Allocation Library that uses services from the SMM Services Table to +// allocate and free memory. +// +// Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library using SMM Services Table" + +#string STR_MODULE_DESCRIPTION #language en-US "This Memory Allocation Library uses services from the SMM Services Table to allocate and free memory." + diff --git a/roms/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/roms/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c new file mode 100644 index 000000000..35b9f775a --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c @@ -0,0 +1,1424 @@ +/** @file + Functions in this library instance make use of MMIO functions in IoLib to + access memory mapped PCI configuration space. + + All assertions for I/O operations are handled in MMIO functions in the IoLib + Library. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved. + Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +/// +/// Module global that contains the base physical address of the PCI Express MMIO range. +/// +UINTN mSmmPciExpressLibPciExpressBaseAddress = 0; + +/** + The constructor function caches the PCI Express Base Address + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor completed successfully. +**/ +EFI_STATUS +EFIAPI +SmmPciExpressLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache the physical address of the PCI Express MMIO range into a module global variable + // + mSmmPciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress); + + return EFI_SUCCESS; +} + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A) \ + ASSERT (((A) & ~0xfffffff) == 0) + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration + registers associated with that PCI device may be accessed after SetVirtualAddressMap() + is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciExpressRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return RETURN_UNSUPPORTED; +} + +/** + Gets MMIO address that can be used to access PCI Express location defined by Address. + + This internal functions converts PCI Express address to a CPU MMIO address by adding + PCI Express Base Address stored in a global variable mSmmPciExpressLibPciExpressBaseAddress. + mSmmPciExpressLibPciExpressBaseAddress is initialized in the library constructor from PCD entry + PcdPciExpressBaseAddress. + + @param Address The address that encodes the PCI Bus, Device, Function and Register. + @return MMIO address corresponding to Address. + +**/ +UINTN +GetPciExpressAddress ( + IN UINTN Address + ) +{ + // + // Make sure Address is valid + // + ASSERT_INVALID_PCI_ADDRESS (Address); + return mSmmPciExpressLibPciExpressBaseAddress + Address; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ) +{ + return MmioRead8 (GetPciExpressAddress (Address)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return MmioWrite8 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioOr8 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioAnd8 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioAndThenOr8 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioBitFieldWrite8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioBitFieldOr8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioBitFieldAnd8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioBitFieldAndThenOr8 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ) +{ + return MmioRead16 (GetPciExpressAddress (Address)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return MmioWrite16 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioOr16 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioAnd16 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioAndThenOr16 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioBitFieldWrite16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioBitFieldOr16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioBitFieldAnd16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioBitFieldAndThenOr16 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ) +{ + return MmioRead32 (GetPciExpressAddress (Address)); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return MmioWrite32 (GetPciExpressAddress (Address), Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioOr32 (GetPciExpressAddress (Address), OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioAnd32 (GetPciExpressAddress (Address), AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioAndThenOr32 ( + GetPciExpressAddress (Address), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return MmioBitFieldRead32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioBitFieldWrite32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioBitFieldOr32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioBitFieldAnd32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioBitFieldAndThenOr32 ( + GetPciExpressAddress (Address), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size read data from StartAddress. + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + // + // Make sure Address is valid + // + ASSERT_INVALID_PCI_ADDRESS (StartAddress); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress)); + + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAddress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + // + // Make sure Address is valid + // + ASSERT_INVALID_PCI_ADDRESS (StartAddress); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & 1) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/roms/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf new file mode 100644 index 000000000..729f6a308 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf @@ -0,0 +1,37 @@ +## @file +# Instance of PCI Express Library using the 256 MB PCI Express MMIO window. +# +# PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +# PCI Configuration cycles. Layers on top of an I/O Library instance. +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved. +# Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmPciExpressLib + FILE_GUID = 00D24382-8231-4B18-A4F0-2D94D8FE2E81 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciExpressLib|DXE_SMM_DRIVER SMM_CORE + CONSTRUCTOR = SmmPciExpressLibConstructor + +[Sources] + PciExpressLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + PcdLib + DebugLib + IoLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES diff --git a/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c new file mode 100644 index 000000000..49ea99ce1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c @@ -0,0 +1,1427 @@ +/** @file + PCI Library using SMM PCI Root Bridge I/O Protocol. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include + + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A,M) \ + ASSERT (((A) & (~0xfffffff | (M))) == 0) + +/** + Translate PCI Lib address into format of PCI Root Bridge I/O Protocol. + + @param A The address that encodes the PCI Bus, Device, Function and + Register. + +**/ +#define PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS(A) \ + ((((A) << 4) & 0xff000000) | (((A) >> 4) & 0x00000700) | (((A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) + +// +// Global variable to cache pointer to PCI Root Bridge I/O protocol. +// +EFI_SMM_PCI_ROOT_BRIDGE_IO_PROTOCOL *mSmmPciRootBridgeIo = NULL; + +/** + The constructor function caches the pointer to PCI Root Bridge I/O protocol. + + The constructor function locates PCI Root Bridge I/O protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PciLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gSmst->SmmLocateProtocol (&gEfiSmmPciRootBridgeIoProtocolGuid, NULL, (VOID**) &mSmmPciRootBridgeIo); + ASSERT_EFI_ERROR (Status); + ASSERT (mSmmPciRootBridgeIo != NULL); + + return EFI_SUCCESS; +} + +/** + Internal worker function to read a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read() service. + It reads and returns the PCI configuration register specified by Address, + the width of data is specified by Width. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to read + + @return The value read from the PCI configuration register. + +**/ +UINT32 +SmmPciLibPciRootBridgeIoReadWorker ( + IN UINTN Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width + ) +{ + UINT32 Data; + + mSmmPciRootBridgeIo->Pci.Read ( + mSmmPciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + + return Data; +} + +/** + Internal worker function to writes a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Write() service. + It writes the PCI configuration register specified by Address with the + value specified by Data. The width of data is specified by Width. + Data is returned. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +SmmPciLibPciRootBridgeIoWriteWorker ( + IN UINTN Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT32 Data + ) +{ + mSmmPciRootBridgeIo->Pci.Write ( + mSmmPciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + return Data; +} + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + return RETURN_UNSUPPORTED; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) ((PciRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciWrite8 ( + Address, + BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldOr8 (PciRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciWrite8 ( + Address, + BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldAndThenOr8 (PciRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) ((PciRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciWrite16 ( + Address, + BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciWrite16 ( + Address, + BitFieldAnd16 (PciRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldAndThenOr16 (PciRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, (PciRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciWrite32 ( + Address, + BitFieldWrite32 (PciRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldOr32 (PciRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciWrite32 ( + Address, + BitFieldAnd32 (PciRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldAndThenOr32 (PciRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAddress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf new file mode 100644 index 000000000..5ac5b48e4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf @@ -0,0 +1,50 @@ +## @file +# PCI Library that layers on top of the SMM PCI Root Bridge I/O Protocol. +# +# This library produces the APIs from the PCI Library and implements these APIs +# by calling into SMM PCI Root Bridge I/O Protocol. SMM PCI Root Bridge I/O Protocol is +# typically produced by a chipset specific SMM driver. +# This library binds to the first SMM PCI Root Bridge I/O Protocol in the platform. As a result, +# it should only be used on platforms that contain a single PCI root bridge. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmPciLibPciRootBridgeIo + MODULE_UNI_FILE = SmmPciLibPciRootBridgeIo.uni + FILE_GUID = F6994CBA-2351-4ebc-A2DA-20BAC2FE2CF3 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib|DXE_SMM_DRIVER SMM_CORE + PI_SPECIFICATION_VERSION = 0x0001000A + CONSTRUCTOR = PciLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + PciLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + SmmServicesTableLib + DebugLib + +[Protocols] + gEfiSmmPciRootBridgeIoProtocolGuid ## CONSUMES + +[Depex.common.DXE_SMM_DRIVER] + gEfiSmmPciRootBridgeIoProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni new file mode 100644 index 000000000..cfdfe6992 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni @@ -0,0 +1,20 @@ +// /** @file +// PCI Library that layers on top of the SMM PCI Root Bridge I/O Protocol. +// +// This library produces the APIs from the PCI Library and implements these APIs +// by calling into SMM PCI Root Bridge I/O Protocol. SMM PCI Root Bridge I/O Protocol is +// typically produced by a chipset specific SMM driver. +// This library binds to the first SMM PCI Root Bridge I/O Protocol in the platform. As a result, +// it should only be used on platforms that contain a single PCI root bridge. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCI Library that layers on top of the SMM PCI Root Bridge I/O Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "This library produces the APIs from the PCI Library and implements these APIs by calling into SMM PCI Root Bridge I/O Protocol. SMM PCI Root Bridge I/O Protocol is typically produced by a chipset-specific SMM driver. This library binds to the first SMM PCI Root Bridge I/O Protocol in the platform. As a result, it should only be used on platforms that contain a single PCI root bridge." + diff --git a/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c new file mode 100644 index 000000000..8b1e780b7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c @@ -0,0 +1,1169 @@ +/** @file + SMM Periodic SMI Library. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/// +/// Define the number of periodic SMI handler entries that should be allocated to the list +/// of free periodic SMI handlers when the list of free periodic SMI handlers is empty. +/// +#define PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE 0x08 + +/// +/// Signature for a PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT structure +/// +#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE SIGNATURE_32 ('P', 'S', 'M', 'I') + +/// +/// Structure that contains state information for an enabled periodic SMI handler +/// +typedef struct { + /// + /// Signature value that must be set to PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE + /// + UINT32 Signature; + /// + /// The link entry to be inserted to the list of periodic SMI handlers. + /// + LIST_ENTRY Link; + /// + /// The dispatch function to called to invoke an enabled periodic SMI handler. + /// + PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction; + /// + /// The context to pass into DispatchFunction + /// + VOID *Context; + /// + /// The tick period in 100 ns units that DispatchFunction should be called. + /// + UINT64 TickPeriod; + /// + /// The Cpu number that is required to execute DispatchFunction. If Cpu is + /// set to PERIODIC_SMI_LIBRARY_ANY_CPU, then DispatchFunction may be executed + /// on any CPU. + /// + UINTN Cpu; + /// + /// The size, in bytes, of the stack allocated for a periodic SMI handler. + /// This value must be a multiple of EFI_PAGE_SIZE. + /// + UINTN StackSize; + /// + /// A pointer to the stack allocated using AllocatePages(). This field will + /// be NULL if StackSize is 0. + /// + VOID *Stack; + /// + /// Spin lock used to wait for an AP to complete the execution of a periodic SMI handler + /// + SPIN_LOCK DispatchLock; + /// + /// The rate in Hz of the performance counter that is used to measure the + /// amount of time that a periodic SMI handler executes. + /// + UINT64 PerfomanceCounterRate; + /// + /// The start count value of the performance counter that is used to measure + /// the amount of time that a periodic SMI handler executes. + /// + UINT64 PerfomanceCounterStartValue; + /// + /// The end count value of the performance counter that is used to measure + /// the amount of time that a periodic SMI handler executes. + /// + UINT64 PerfomanceCounterEndValue; + /// + /// The context record passed into the Register() function of the SMM Periodic + /// Timer Dispatch Protocol when a periodic SMI handler is enabled. + /// + EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT RegisterContext; + /// + /// The handle returned from the Register() function of the SMM Periodic + /// Timer Dispatch Protocol when a periodic SMI handler is enabled. + /// + EFI_HANDLE DispatchHandle; + /// + /// The total number of performance counter ticks that the periodic SMI handler + /// has been executing in its current invocation. + /// + UINT64 DispatchTotalTime; + /// + /// The performance counter value that was captured the last time that the + /// periodic SMI handler called PeriodicSmiExecutionTime(). This allows the + /// time value returned by PeriodicSmiExecutionTime() to be accurate even when + /// the performance counter rolls over. + /// + UINT64 DispatchCheckPointTime; + /// + /// Buffer used to save the context when control is transfer from this library + /// to an enabled periodic SMI handler. This saved context is used when the + /// periodic SMI handler exits or yields. + /// + BASE_LIBRARY_JUMP_BUFFER DispatchJumpBuffer; + /// + /// Flag that is set to TRUE when a periodic SMI handler requests to yield + /// using PeriodicSmiYield(). When this flag IS TRUE, YieldJumpBuffer is + /// valid. When this flag is FALSE, YieldJumpBuffer is not valid. + /// + BOOLEAN YieldFlag; + /// + /// Buffer used to save the context when a periodic SMI handler requests to + /// yield using PeriodicSmiYield(). This context is used to resume the + /// execution of a periodic SMI handler the next time control is transferred + /// to the periodic SMI handler that yielded. + /// + BASE_LIBRARY_JUMP_BUFFER YieldJumpBuffer; + /// + /// The amount of time, in 100 ns units, that have elapsed since the last + /// time the periodic SMI handler was invoked. + /// + UINT64 ElapsedTime; +} PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT; + +/** + Macro that returns a pointer to a PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT + structure based on a pointer to a Link field. + +**/ +#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK(a) \ + CR ( \ + a, \ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT, \ + Link, \ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE \ + ) + +/// +/// Pointer to the SMM Periodic Timer Dispatch Protocol that was located in the constructor. +/// +EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *gSmmPeriodicTimerDispatch2 = NULL; + +/// +/// Pointer to a table of supported periodic SMI tick periods in 100 ns units +/// sorted from largest to smallest terminated by a tick period value of 0. +/// This table is allocated using AllocatePool() in the constructor and filled +/// in based on the values returned from the SMM Periodic Timer Dispatch 2 Protocol +/// function GetNextShorterInterval(). +/// +UINT64 *gSmiTickPeriodTable = NULL; + +/// +/// Linked list of free periodic SMI handlers that this library can use. +/// +LIST_ENTRY gFreePeriodicSmiLibraryHandlers = + INITIALIZE_LIST_HEAD_VARIABLE (gFreePeriodicSmiLibraryHandlers); + +/// +/// Linked list of periodic SMI handlers that this library is currently managing. +/// +LIST_ENTRY gPeriodicSmiLibraryHandlers = + INITIALIZE_LIST_HEAD_VARIABLE (gPeriodicSmiLibraryHandlers); + +/// +/// Pointer to the periodic SMI handler that is currently being executed. +/// Is set to NULL if no periodic SMI handler is currently being executed. +/// +PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *gActivePeriodicSmiLibraryHandler = NULL; + +/** + Internal worker function that returns a pointer to the + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT structure associated with the periodic + SMI handler that is currently being executed. If a periodic SMI handler is + not currently being executed, the NULL is returned. + + @retval NULL A periodic SMI handler is not currently being executed. + @retval other Pointer to the PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT + associated with the active periodic SMI handler. + +**/ +PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * +GetActivePeriodicSmiLibraryHandler ( + VOID + ) +{ + return gActivePeriodicSmiLibraryHandler; +} + +/** + Internal worker function that returns a pointer to the + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT structure associated with the + DispatchHandle that was returned when the periodic SMI handler was enabled + with PeriodicSmiEnable(). If DispatchHandle is NULL, then the active + periodic SMI handler is returned. If DispatchHandle is NULL and there is + no active periodic SMI handler, then NULL is returned. + + @param[in] DispatchHandle DispatchHandle that was returned when the periodic + SMI handler was enabled with PeriodicSmiEnable(). + This is an optional parameter that may be NULL. + If this parameter is NULL, then the active periodic + SMI handler is returned. + + @retval NULL DispatchHandle is NULL and there is no active periodic SMI + handler. + @retval NULL DispatchHandle does not match any of the periodic SMI handlers + that have been enabled with PeriodicSmiEnable(). + @retval other Pointer to the PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT + associated with the DispatchHandle. + +**/ +PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * +LookupPeriodicSmiLibraryHandler ( + IN EFI_HANDLE DispatchHandle OPTIONAL + ) +{ + LIST_ENTRY *Link; + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // If DispatchHandle is NULL, then return the active periodic SMI handler + // + if (DispatchHandle == NULL) { + return GetActivePeriodicSmiLibraryHandler (); + } + + // + // Search the periodic SMI handler entries for a a matching DispatchHandle + // + for ( Link = GetFirstNode (&gPeriodicSmiLibraryHandlers) + ; !IsNull (&gPeriodicSmiLibraryHandlers, Link) + ; Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link) + ) { + PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link); + + if (PeriodicSmiLibraryHandler->DispatchHandle == DispatchHandle) { + return PeriodicSmiLibraryHandler; + } + } + + // + // No entries match DispatchHandle, so return NULL + // + return NULL; +} + +/** + Internal worker function that sets that active periodic SMI handler based on + the DispatchHandle that was returned when the periodic SMI handler was enabled + with PeriodicSmiEnable(). If DispatchHandle is NULL, then the + state is updated to show that there is not active periodic SMI handler. + A pointer to the active PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT structure + is returned. + + @param [in] DispatchHandle DispatchHandle that was returned when the periodic + SMI handler was enabled with PeriodicSmiEnable(). + This is an optional parameter that may be NULL. + If this parameter is NULL, then the state is updated + to show that there is not active periodic SMI handler. + @retval NULL DispatchHandle is NULL. + @retval other Pointer to the PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT + associated with DispatchHandle. + +**/ +PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * +SetActivePeriodicSmiLibraryHandler ( + IN EFI_HANDLE DispatchHandle OPTIONAL + ) +{ + if (DispatchHandle == NULL) { + gActivePeriodicSmiLibraryHandler = NULL; + } else { + gActivePeriodicSmiLibraryHandler = LookupPeriodicSmiLibraryHandler (DispatchHandle); + } + return gActivePeriodicSmiLibraryHandler; +} + +/** + Internal worker function that moves the specified periodic SMI handler from the + list of managed periodic SMI handlers to the list of free periodic SMI handlers. + + @param[in] PeriodicSmiLibraryHandler Pointer to the periodic SMI handler to be reclaimed. +**/ +VOID +ReclaimPeriodicSmiLibraryHandler ( + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler + ) +{ + ASSERT (PeriodicSmiLibraryHandler->DispatchHandle == NULL); + if (PeriodicSmiLibraryHandler->Stack != NULL) { + FreePages ( + PeriodicSmiLibraryHandler->Stack, + EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize) + ); + PeriodicSmiLibraryHandler->Stack = NULL; + } + RemoveEntryList (&PeriodicSmiLibraryHandler->Link); + InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link); +} + +/** + Add the additional entries to the list of free periodic SMI handlers. + The function is assumed to be called only when the list of free periodic SMI + handlers is empty. + + @retval TRUE The additional entries were added. + @retval FALSE There was no available resource for the additional entries. +**/ +BOOLEAN +EnlargeFreePeriodicSmiLibraryHandlerList ( + VOID + ) +{ + UINTN Index; + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // Add the entries to the list + // + for (Index = 0; Index < PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE; Index++) { + PeriodicSmiLibraryHandler = AllocatePool (sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT)); + if (PeriodicSmiLibraryHandler == NULL) { + break; + } + PeriodicSmiLibraryHandler->Signature = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE; + InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link); + } + + return (BOOLEAN) (Index > 0); +} + +/** + Internal worker function that returns a free entry for a new periodic + SMI handler. If no free entries are available, then additional + entries are allocated. + + @retval NULL There are not enough resources available to to allocate a free entry. + @retval other Pointer to a free PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT structure. + +**/ +PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * +FindFreePeriodicSmiLibraryHandler ( + VOID + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + if (IsListEmpty (&gFreePeriodicSmiLibraryHandlers)) { + if (!EnlargeFreePeriodicSmiLibraryHandlerList ()) { + return NULL; + } + } + + // + // Get one from the list of free periodic SMI handlers. + // + PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK ( + GetFirstNode (&gFreePeriodicSmiLibraryHandlers) + ); + RemoveEntryList (&PeriodicSmiLibraryHandler->Link); + InsertTailList (&gPeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link); + + return PeriodicSmiLibraryHandler; +} + +/** + This function returns a pointer to a table of supported periodic + SMI tick periods in 100 ns units sorted from largest to smallest. + The table contains a array of UINT64 values terminated by a tick + period value of 0. The returned table must be treated as read-only + data and must not be freed. + + @return A pointer to a table of UINT64 tick period values in + 100ns units sorted from largest to smallest terminated + by a tick period of 0. + +**/ +UINT64 * +EFIAPI +PeriodicSmiSupportedTickPeriod ( + VOID + ) +{ + // + // Return the table allocated and populated by SmmPeriodicSmiLibConstructor() + // + return gSmiTickPeriodTable; +} + +/** + This function returns the time in 100ns units since the periodic SMI + handler function was called. If the periodic SMI handler was resumed + through PeriodicSmiYield(), then the time returned is the time in + 100ns units since PeriodicSmiYield() returned. + + @return The actual time in 100ns units that the periodic SMI handler + has been executing. If this function is not called from within + an enabled periodic SMI handler, then 0 is returned. + +**/ +UINT64 +EFIAPI +PeriodicSmiExecutionTime ( + VOID + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + UINT64 Current; + UINT64 Count; + + // + // If there is no active periodic SMI handler, then return 0 + // + PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler (); + if (PeriodicSmiLibraryHandler == NULL) { + return 0; + } + + // + // Get the current performance counter value + // + Current = GetPerformanceCounter (); + + // + // Count the number of performance counter ticks since the periodic SMI handler + // was dispatched or the last time this function was called. + // + if (PeriodicSmiLibraryHandler->PerfomanceCounterEndValue > PeriodicSmiLibraryHandler->PerfomanceCounterStartValue) { + // + // The performance counter counts up. Check for roll over condition. + // + if (Current > PeriodicSmiLibraryHandler->DispatchCheckPointTime) { + Count = Current - PeriodicSmiLibraryHandler->DispatchCheckPointTime; + } else { + Count = (Current - PeriodicSmiLibraryHandler->PerfomanceCounterStartValue) + (PeriodicSmiLibraryHandler->PerfomanceCounterEndValue - PeriodicSmiLibraryHandler->DispatchCheckPointTime); + } + } else { + // + // The performance counter counts down. Check for roll over condition. + // + if (PeriodicSmiLibraryHandler->DispatchCheckPointTime > Current) { + Count = PeriodicSmiLibraryHandler->DispatchCheckPointTime - Current; + } else { + Count = (PeriodicSmiLibraryHandler->DispatchCheckPointTime - PeriodicSmiLibraryHandler->PerfomanceCounterEndValue) + (PeriodicSmiLibraryHandler->PerfomanceCounterStartValue - Current); + } + } + + // + // Accumulate the total number of performance counter ticks since the periodic + // SMI handler was dispatched or resumed. + // + PeriodicSmiLibraryHandler->DispatchTotalTime += Count; + + // + // Update the checkpoint value to the current performance counter value + // + PeriodicSmiLibraryHandler->DispatchCheckPointTime = Current; + + // + // Convert the total number of performance counter ticks to 100 ns units + // + return DivU64x64Remainder ( + MultU64x32 (PeriodicSmiLibraryHandler->DispatchTotalTime, 10000000), + PeriodicSmiLibraryHandler->PerfomanceCounterRate, + NULL + ); +} + +/** + This function returns control back to the SMM Foundation. When the next + periodic SMI for the currently executing handler is triggered, the periodic + SMI handler will restarted from its registered DispatchFunction entry point. + If this function is not called from within an enabled periodic SMI handler, + then control is returned to the calling function. + +**/ +VOID +EFIAPI +PeriodicSmiExit ( + VOID + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // If there is no active periodic SMI handler, then return + // + PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler (); + if (PeriodicSmiLibraryHandler == NULL) { + return; + } + + // + // Perform a long jump back to the point when the currently executing dispatch + // function was dispatched. + // + LongJump (&PeriodicSmiLibraryHandler->DispatchJumpBuffer, 1); + + // + // Must never return + // + ASSERT (FALSE); + CpuDeadLoop(); +} + +/** + This function yields control back to the SMM Foundation. When the next + periodic SMI for the currently executing handler is triggered, the periodic + SMI handler will be resumed and this function will return. Use of this + function requires a separate stack for the periodic SMI handler. A non zero + stack size must be specified in PeriodicSmiEnable() for this function to be + used. + + If the stack size passed into PeriodicSmiEnable() was zero, the 0 is returned. + + If this function is not called from within an enabled periodic SMI handler, + then 0 is returned. + + @return The actual time in 100ns units elapsed since this function was + called. A value of 0 indicates an unknown amount of time. + +**/ +UINT64 +EFIAPI +PeriodicSmiYield ( + VOID + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + UINTN SetJumpFlag; + + // + // If there is no active periodic SMI handler, then return + // + PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler (); + if (PeriodicSmiLibraryHandler == NULL) { + return 0; + } + + // + // If PeriodicSmiYield() is called without an allocated stack, then just return + // immediately with an elapsed time of 0. + // + if (PeriodicSmiLibraryHandler->Stack == NULL) { + return 0; + } + + // + // Set a flag so the next periodic SMI event will resume at where SetJump() + // is called below. + // + PeriodicSmiLibraryHandler->YieldFlag = TRUE; + + // + // Save context in YieldJumpBuffer + // + SetJumpFlag = SetJump (&PeriodicSmiLibraryHandler->YieldJumpBuffer); + if (SetJumpFlag == 0) { + // + // The initial call to SetJump() always returns 0. + // If this is the initial call, then exit the current periodic SMI handler + // + PeriodicSmiExit (); + } + + // + // We get here when a LongJump is performed from PeriodicSmiDispatchFunctionOnCpu() + // to resume a periodic SMI handler that called PeriodicSmiYield() on the + // previous time this periodic SMI handler was dispatched. + // + // Clear the flag so the next periodic SMI dispatch will not resume. + // + PeriodicSmiLibraryHandler->YieldFlag = FALSE; + + // + // Return the amount elapsed time that occurred while yielded + // + return PeriodicSmiLibraryHandler->ElapsedTime; +} + +/** + Internal worker function that transfers control to an enabled periodic SMI + handler. If the enabled periodic SMI handler was allocated its own stack, + then this function is called on that allocated stack through the BaseLin + function SwitchStack(). + + @param[in] Context1 Context1 parameter passed into SwitchStack(). + @param[in] Context2 Context2 parameter passed into SwitchStack(). + +**/ +VOID +EFIAPI +PeriodicSmiDispatchFunctionSwitchStack ( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // Convert Context1 to PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * + // + PeriodicSmiLibraryHandler = (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *)Context1; + + // + // Dispatch the registered handler passing in the context that was registered + // and the amount of time that has elapsed since the previous time this + // periodic SMI handler was dispatched. + // + PeriodicSmiLibraryHandler->DispatchFunction ( + PeriodicSmiLibraryHandler->Context, + PeriodicSmiLibraryHandler->ElapsedTime + ); + + // + // If this DispatchFunction() returns, then unconditionally call PeriodicSmiExit() + // to perform a LongJump() back to PeriodicSmiDispatchFunctionOnCpu(). The + // LongJump() will resume execution on the original stack. + // + PeriodicSmiExit (); +} + +/** + Internal worker function that transfers control to an enabled periodic SMI + handler on the specified logical CPU. This function determines if the periodic + SMI handler yielded and needs to be resumed. It also and switches to an + allocated stack if one was allocated in PeriodicSmiEnable(). + + @param[in] PeriodicSmiLibraryHandler A pointer to the context for the periodic + SMI handler to execute. + +**/ +VOID +EFIAPI +PeriodicSmiDispatchFunctionOnCpu ( + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler + ) +{ + // + // Save context in DispatchJumpBuffer. The initial call to SetJump() always + // returns 0. If this is the initial call, then either resume from a prior + // call to PeriodicSmiYield() or call the DispatchFunction registered in + // PeriodicSmiEnable() using an allocated stack if one was specified. + // + if (SetJump (&PeriodicSmiLibraryHandler->DispatchJumpBuffer) != 0) { + return; + } + + // + // Capture the performance counter value just before the periodic SMI handler + // is resumed so the amount of time the periodic SMI handler executes can be + // calculated. + // + PeriodicSmiLibraryHandler->DispatchTotalTime = 0; + PeriodicSmiLibraryHandler->DispatchCheckPointTime = GetPerformanceCounter(); + + if (PeriodicSmiLibraryHandler->YieldFlag) { + // + // Perform a long jump back to the point where the previously dispatched + // function called PeriodicSmiYield(). + // + LongJump (&PeriodicSmiLibraryHandler->YieldJumpBuffer, 1); + } else if (PeriodicSmiLibraryHandler->Stack == NULL) { + // + // If Stack is NULL then call DispatchFunction using current stack passing + // in the context that was registered and the amount of time that has + // elapsed since the previous time this periodic SMI handler was dispatched. + // + PeriodicSmiLibraryHandler->DispatchFunction ( + PeriodicSmiLibraryHandler->Context, + PeriodicSmiLibraryHandler->ElapsedTime + ); + + // + // If this DispatchFunction() returns, then unconditionally call PeriodicSmiExit() + // to perform a LongJump() back to this function. + // + PeriodicSmiExit (); + } else { + // + // If Stack is not NULL then call DispatchFunction switching to the allocated stack + // + SwitchStack ( + PeriodicSmiDispatchFunctionSwitchStack, + PeriodicSmiLibraryHandler, + NULL, + (UINT8 *)PeriodicSmiLibraryHandler->Stack + PeriodicSmiLibraryHandler->StackSize + ); + } + + // + // Must never return + // + ASSERT (FALSE); + CpuDeadLoop(); +} + +/** + Internal worker function that transfers control to an enabled periodic SMI + handler on the specified logical CPU. This worker function is only called + using the SMM Services Table function SmmStartupThisAp() to execute the + periodic SMI handler on a logical CPU that is different than the one that is + running the SMM Foundation. When the periodic SMI handler returns, a lock is + released to notify the CPU that is running the SMM Foundation that the periodic + SMI handler execution has finished its execution. + + @param[in, out] Buffer A pointer to the context for the periodic SMI handler. + +**/ +VOID +EFIAPI +PeriodicSmiDispatchFunctionWithLock ( + IN OUT VOID *Buffer + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // Get context + // + PeriodicSmiLibraryHandler = (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *)Buffer; + + // + // Execute dispatch function on the currently executing logical CPU + // + PeriodicSmiDispatchFunctionOnCpu (PeriodicSmiLibraryHandler); + + // + // Release the dispatch spin lock + // + ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock); +} + +/** + Internal worker function that transfers control to a periodic SMI handler that + was enabled using PeriodicSmiEnable(). + + @param[in] DispatchHandle The unique handle assigned to this handler by + SmiHandlerRegister(). + @param[in] Context Points to an optional handler context which was + specified when the handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in memory that + will be conveyed from a non-SMM environment into + an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled and quiesced. + No other handlers should still be called. + @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other + handlers should still be called. + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other + handlers should still be called. + @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced. + +**/ +EFI_STATUS +EFIAPI +PeriodicSmiDispatchFunction ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + EFI_SMM_PERIODIC_TIMER_CONTEXT *TimerContext; + EFI_STATUS Status; + + // + // Set the active periodic SMI handler + // + PeriodicSmiLibraryHandler = SetActivePeriodicSmiLibraryHandler (DispatchHandle); + if (PeriodicSmiLibraryHandler == NULL) { + return EFI_NOT_FOUND; + } + + // + // Retrieve the elapsed time since the last time this periodic SMI handler was called + // + PeriodicSmiLibraryHandler->ElapsedTime = 0; + if (CommBuffer != NULL) { + TimerContext = (EFI_SMM_PERIODIC_TIMER_CONTEXT *)CommBuffer; + PeriodicSmiLibraryHandler->ElapsedTime = TimerContext->ElapsedTime; + } + + // + // Dispatch the periodic SMI handler + // + if ((PeriodicSmiLibraryHandler->Cpu == PERIODIC_SMI_LIBRARY_ANY_CPU) || + (PeriodicSmiLibraryHandler->Cpu == gSmst->CurrentlyExecutingCpu) ) { + // + // Dispatch on the currently execution CPU if the CPU specified in PeriodicSmiEnable() + // was PERIODIC_SMI_LIBRARY_ANY_CPU or the currently executing CPU matches the CPU + // that was specified in PeriodicSmiEnable(). + // + PeriodicSmiDispatchFunctionOnCpu (PeriodicSmiLibraryHandler); + } else { + // + // Acquire spin lock for ths periodic SMI handler. The AP will release the + // spin lock when it is done executing the periodic SMI handler. + // + AcquireSpinLock (&PeriodicSmiLibraryHandler->DispatchLock); + + // + // Execute the periodic SMI handler on the CPU that was specified in + // PeriodicSmiEnable(). + // + Status = gSmst->SmmStartupThisAp ( + PeriodicSmiDispatchFunctionWithLock, + PeriodicSmiLibraryHandler->Cpu, + PeriodicSmiLibraryHandler + ); + if (!EFI_ERROR (Status)) { + // + // Wait for the AP to release the spin lock. + // + while (!AcquireSpinLockOrFail (&PeriodicSmiLibraryHandler->DispatchLock)) { + CpuPause (); + } + } + + // + // Release the spin lock for the periodic SMI handler. + // + ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock); + } + + // + // Reclaim the active periodic SMI handler if it was disabled during the current dispatch. + // + if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) { + ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler); + } + + // + // Update state to show that there is no active periodic SMI handler + // + SetActivePeriodicSmiLibraryHandler (NULL); + + return EFI_SUCCESS; +} + +/** + This function enables a periodic SMI handler. + + @param[in, out] DispatchHandle A pointer to the handle associated with the + enabled periodic SMI handler. This is an + optional parameter that may be NULL. If it is + NULL, then the handle will not be returned, + which means that the periodic SMI handler can + never be disabled. + @param[in] DispatchFunction A pointer to a periodic SMI handler function. + @param[in] Context Optional content to pass into DispatchFunction. + @param[in] TickPeriod The requested tick period in 100ns units that + control should be given to the periodic SMI + handler. Must be one of the supported values + returned by PeriodicSmiSupportedPickPeriod(). + @param[in] Cpu Specifies the CPU that is required to execute + the periodic SMI handler. If Cpu is + PERIODIC_SMI_LIBRARY_ANY_CPU, then the periodic + SMI handler will always be executed on the SMST + CurrentlyExecutingCpu, which may vary across + periodic SMIs. If Cpu is between 0 and the SMST + NumberOfCpus, then the periodic SMI will always + be executed on the requested CPU. + @param[in] StackSize The size, in bytes, of the stack to allocate for + use by the periodic SMI handler. If 0, then the + default stack will be used. + + @retval EFI_INVALID_PARAMETER DispatchFunction is NULL. + @retval EFI_UNSUPPORTED TickPeriod is not a supported tick period. The + supported tick periods can be retrieved using + PeriodicSmiSupportedTickPeriod(). + @retval EFI_INVALID_PARAMETER Cpu is not PERIODIC_SMI_LIBRARY_ANY_CPU or in + the range 0 to SMST NumberOfCpus. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to enable the + periodic SMI handler. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the + stack specified by StackSize. + @retval EFI_SUCCESS The periodic SMI handler was enabled. + +**/ +EFI_STATUS +EFIAPI +PeriodicSmiEnable ( + IN OUT EFI_HANDLE *DispatchHandle, OPTIONAL + IN PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction, + IN CONST VOID *Context, OPTIONAL + IN UINT64 TickPeriod, + IN UINTN Cpu, + IN UINTN StackSize + ) +{ + EFI_STATUS Status; + UINTN Index; + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // Make sure all the input parameters are valid + // + if (DispatchFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; gSmiTickPeriodTable[Index] != 0; Index++) { + if (gSmiTickPeriodTable[Index] == TickPeriod) { + break; + } + } + if (gSmiTickPeriodTable[Index] == 0) { + return EFI_UNSUPPORTED; + } + + if (Cpu != PERIODIC_SMI_LIBRARY_ANY_CPU && Cpu >= gSmst->NumberOfCpus) { + return EFI_INVALID_PARAMETER; + } + + // + // Find a free periodic SMI handler entry + // + PeriodicSmiLibraryHandler = FindFreePeriodicSmiLibraryHandler(); + if (PeriodicSmiLibraryHandler == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize a new periodic SMI handler entry + // + PeriodicSmiLibraryHandler->YieldFlag = FALSE; + PeriodicSmiLibraryHandler->DispatchHandle = NULL; + PeriodicSmiLibraryHandler->DispatchFunction = DispatchFunction; + PeriodicSmiLibraryHandler->Context = (VOID *)Context; + PeriodicSmiLibraryHandler->Cpu = Cpu; + PeriodicSmiLibraryHandler->StackSize = ALIGN_VALUE (StackSize, EFI_PAGE_SIZE); + if (PeriodicSmiLibraryHandler->StackSize > 0) { + PeriodicSmiLibraryHandler->Stack = AllocatePages (EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)); + if (PeriodicSmiLibraryHandler->Stack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ZeroMem (PeriodicSmiLibraryHandler->Stack, PeriodicSmiLibraryHandler->StackSize); + } else { + PeriodicSmiLibraryHandler->Stack = NULL; + } + InitializeSpinLock (&PeriodicSmiLibraryHandler->DispatchLock); + PeriodicSmiLibraryHandler->PerfomanceCounterRate = GetPerformanceCounterProperties ( + &PeriodicSmiLibraryHandler->PerfomanceCounterStartValue, + &PeriodicSmiLibraryHandler->PerfomanceCounterEndValue + ); + PeriodicSmiLibraryHandler->RegisterContext.Period = TickPeriod; + PeriodicSmiLibraryHandler->RegisterContext.SmiTickInterval = TickPeriod; + Status = gSmmPeriodicTimerDispatch2->Register ( + gSmmPeriodicTimerDispatch2, + PeriodicSmiDispatchFunction, + &PeriodicSmiLibraryHandler->RegisterContext, + &PeriodicSmiLibraryHandler->DispatchHandle + ); + if (EFI_ERROR (Status)) { + PeriodicSmiLibraryHandler->DispatchHandle = NULL; + ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler); + return EFI_OUT_OF_RESOURCES; + } + + // + // Return the registered handle if the optional DispatchHandle parameter is not NULL + // + if (DispatchHandle != NULL) { + *DispatchHandle = PeriodicSmiLibraryHandler->DispatchHandle; + } + return EFI_SUCCESS; +} + +/** + This function disables a periodic SMI handler that has been previously + enabled with PeriodicSmiEnable(). + + @param[in] DispatchHandle A handle associated with a previously enabled periodic + SMI handler. This is an optional parameter that may + be NULL. If it is NULL, then the active periodic SMI + handlers is disabled. + + @retval FALSE DispatchHandle is NULL and there is no active periodic SMI handler. + @retval FALSE The periodic SMI handler specified by DispatchHandle has + not been enabled with PeriodicSmiEnable(). + @retval TRUE The periodic SMI handler specified by DispatchHandle has + been disabled. If DispatchHandle is NULL, then the active + periodic SMI handler has been disabled. + +**/ +BOOLEAN +EFIAPI +PeriodicSmiDisable ( + IN EFI_HANDLE DispatchHandle OPTIONAL + ) +{ + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + EFI_STATUS Status; + + // + // Lookup the periodic SMI handler specified by DispatchHandle + // + PeriodicSmiLibraryHandler = LookupPeriodicSmiLibraryHandler (DispatchHandle); + if (PeriodicSmiLibraryHandler == NULL) { + return FALSE; + } + + // + // Unregister the periodic SMI handler from the SMM Periodic Timer Dispatch 2 Protocol + // + Status = gSmmPeriodicTimerDispatch2->UnRegister ( + gSmmPeriodicTimerDispatch2, + PeriodicSmiLibraryHandler->DispatchHandle + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Mark the entry for the disabled periodic SMI handler as free, and + // call ReclaimPeriodicSmiLibraryHandler to move it to the list of free + // periodic SMI handlers. + // + PeriodicSmiLibraryHandler->DispatchHandle = NULL; + if (PeriodicSmiLibraryHandler != GetActivePeriodicSmiLibraryHandler ()) { + ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler); + } + + return TRUE; +} + +/** + This constructor function caches the pointer to the SMM Periodic Timer + Dispatch 2 Protocol and collects the list SMI tick rates that the hardware + supports. + + @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 constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmmPeriodicSmiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 *SmiTickInterval; + UINTN Count; + + // + // Locate the SMM Periodic Timer Dispatch 2 Protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmPeriodicTimerDispatch2ProtocolGuid, + NULL, + (VOID **)&gSmmPeriodicTimerDispatch2 + ); + ASSERT_EFI_ERROR (Status); + ASSERT (gSmmPeriodicTimerDispatch2 != NULL); + + // + // Count the number of periodic SMI tick intervals that the SMM Periodic Timer + // Dispatch 2 Protocol supports. + // + SmiTickInterval = NULL; + Count = 0; + do { + Status = gSmmPeriodicTimerDispatch2->GetNextShorterInterval ( + gSmmPeriodicTimerDispatch2, + &SmiTickInterval + ); + Count++; + } while (SmiTickInterval != NULL); + + // + // Allocate a buffer for the table of supported periodic SMI tick periods. + // + gSmiTickPeriodTable = AllocateZeroPool (Count * sizeof (UINT64)); + ASSERT (gSmiTickPeriodTable != NULL); + + // + // Fill in the table of supported periodic SMI tick periods. + // + SmiTickInterval = NULL; + Count = 0; + do { + gSmiTickPeriodTable[Count] = 0; + Status = gSmmPeriodicTimerDispatch2->GetNextShorterInterval ( + gSmmPeriodicTimerDispatch2, + &SmiTickInterval + ); + if (SmiTickInterval != NULL) { + gSmiTickPeriodTable[Count] = *SmiTickInterval; + } + Count++; + } while (SmiTickInterval != NULL); + + // + // Allocate buffer for initial set of periodic SMI handlers + // + EnlargeFreePeriodicSmiLibraryHandlerList (); + + return EFI_SUCCESS; +} + +/** + The constructor function caches the pointer to the SMM Periodic Timer Dispatch 2 + Protocol and collects the list SMI tick rates that the hardware supports. + + @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 constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmmPeriodicSmiLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + LIST_ENTRY *Link; + PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler; + + // + // Free the table of supported periodic SMI tick rates + // + if (gSmiTickPeriodTable != NULL) { + FreePool (gSmiTickPeriodTable); + } + + // + // Disable all periodic SMI handlers + // + for (Link = GetFirstNode (&gPeriodicSmiLibraryHandlers); !IsNull (&gPeriodicSmiLibraryHandlers, Link);) { + PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link); + Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link); + PeriodicSmiDisable (PeriodicSmiLibraryHandler->DispatchHandle); + } + + // + // Free all the periodic SMI handler entries + // + for (Link = GetFirstNode (&gFreePeriodicSmiLibraryHandlers); !IsNull (&gFreePeriodicSmiLibraryHandlers, Link);) { + PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link); + Link = RemoveEntryList (Link); + FreePool (PeriodicSmiLibraryHandler); + } + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf new file mode 100644 index 000000000..8df10105e --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf @@ -0,0 +1,47 @@ +## @file +# SMM Periodic SMI Library. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmPeriodicSmiLib + MODULE_UNI_FILE = SmmPeriodicSmiLib.uni + FILE_GUID = AED5F3FB-4CFF-4b60-9E43-1541B55C8267 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmPeriodicSmiLib|DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION = 0x0001000A + CONSTRUCTOR = SmmPeriodicSmiLibConstructor + DESTRUCTOR = SmmPeriodicSmiLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmPeriodicSmiLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + SynchronizationLib + DebugLib + TimerLib + MemoryAllocationLib + SmmServicesTableLib + +[Protocols] + gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## CONSUMES + +[Depex] + gEfiSmmPeriodicTimerDispatch2ProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni new file mode 100644 index 000000000..0d05e19ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni @@ -0,0 +1,16 @@ +// /** @file +// SMM Periodic SMI Library. +// +// SMM Periodic SMI Library. +// +// Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMM Periodic SMI Library" + +#string STR_MODULE_DESCRIPTION #language en-US "SMM Periodic SMI Library." + diff --git a/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c new file mode 100644 index 000000000..0f611cd25 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c @@ -0,0 +1,79 @@ +/** @file + SMM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +EFI_SMM_SYSTEM_TABLE2 *gSmst = NULL; + +/** + The constructor function caches the pointer of SMM Services Table. + + @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 +SmmServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_BASE2_PROTOCOL *InternalSmmBase2; + + InternalSmmBase2 = NULL; + // + // Retrieve SMM Base2 Protocol, Do not use gBS from UefiBootServicesTableLib on purpose + // to prevent inclusion of gBS, gST, and gImageHandle from SMM Drivers unless the + // SMM driver explicitly declares that dependency. + // + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiSmmBase2ProtocolGuid, + NULL, + (VOID **)&InternalSmmBase2 + ); + ASSERT_EFI_ERROR (Status); + ASSERT (InternalSmmBase2 != NULL); + + // + // We are in SMM, retrieve the pointer to SMM System Table + // + InternalSmmBase2->GetSmstLocation (InternalSmmBase2, &gSmst); + ASSERT (gSmst != NULL); + + return EFI_SUCCESS; +} + +/** + This function allows the caller to determine if the driver is executing in + System Management Mode(SMM). + + This function returns TRUE if the driver is executing in SMM and FALSE if the + driver is not executing in SMM. + + @retval TRUE The driver is executing in System Management Mode (SMM). + @retval FALSE The driver is not executing in System Management Mode (SMM). + +**/ +BOOLEAN +EFIAPI +InSmm ( + VOID + ) +{ + // + // We are already in SMM + // + return TRUE; +} diff --git a/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf new file mode 100644 index 000000000..17d7b3154 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf @@ -0,0 +1,40 @@ +## @file +# SMM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmServicesTableLib + MODULE_UNI_FILE = SmmServicesTableLib.uni + FILE_GUID = 064B4C5B-C5EF-4eff-85DF-65518EF1314D + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmServicesTableLib|DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION = 0x0001000A + CONSTRUCTOR = SmmServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmServicesTableLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + +[Protocols] + gEfiSmmBase2ProtocolGuid ## CONSUMES + +[Depex] + gEfiSmmBase2ProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni new file mode 100644 index 000000000..729a4ae21 --- /dev/null +++ b/roms/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni @@ -0,0 +1,16 @@ +// /** @file +// SMM Services Table Library. +// +// SMM Services Table Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMM Services Table Library" + +#string STR_MODULE_DESCRIPTION #language en-US "SMM Services Table Library." + diff --git a/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c new file mode 100644 index 000000000..2c41e23a0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c @@ -0,0 +1,81 @@ +/** @file + Entry point to a Standalone MM driver. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2018, ARM Ltd. All rights reserved.
+Copyright (c) 2018, Linaro, Limited. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +/** + The entry point of PE/COFF Image for a Standalone MM Driver. + + This function is the entry point for a Standalone MM Driver. + This function must call ProcessLibraryConstructorList() and + ProcessModuleEntryPointList(). + If the return status from ProcessModuleEntryPointList() + is an error status, then ProcessLibraryDestructorList() must be called. + The return value from ProcessModuleEntryPointList() is returned. + If _gMmRevision is not zero and SystemTable->Hdr.Revision is + less than _gMmRevision, then return EFI_INCOMPATIBLE_VERSION. + + @param ImageHandle The image handle of the Standalone MM Driver. + @param MmSystemTable A pointer to the MM System Table. + + @retval EFI_SUCCESS The Standalone MM Driver exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gMmRevision is greater than + MmSystemTable->Hdr.Revision. + @retval Other Return value from + ProcessModuleEntryPointList(). + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + EFI_STATUS Status; + + if (_gMmRevision != 0) { + // + // Make sure that the MM spec revision of the platform + // is >= MM spec revision of the driver + // + if (MmSystemTable->Hdr.Revision < _gMmRevision) { + return EFI_INCOMPATIBLE_VERSION; + } + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (ImageHandle, MmSystemTable); + + // + // Call the driver entry point + // + Status = ProcessModuleEntryPointList (ImageHandle, MmSystemTable); + + // + // If all of the drivers returned errors, then invoke all of the library destructors + // + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, MmSystemTable); + } + + // + // Return the cumulative return status code from all of the driver entry points + // + return Status; +} diff --git a/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf new file mode 100644 index 000000000..2f33a6d4a --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf @@ -0,0 +1,38 @@ +## @file +# Module entry point library for Standalone MM driver. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.
+# Copyright (c) 2018, Linaro, Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = StandaloneMmDriverEntryPoint + MODULE_UNI_FILE = StandaloneMmDriverEntryPoint.uni + FILE_GUID = 5ca126c0-b598-4f4b-abb9-b6e7d077aea9 + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + LIBRARY_CLASS = StandaloneMmDriverEntryPoint|MM_STANDALONE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources] + StandaloneMmDriverEntryPoint.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + MmServicesTableLib diff --git a/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni new file mode 100644 index 000000000..917ae9514 --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni @@ -0,0 +1,17 @@ +// /** @file +// +// Module entry point library for standalone MM driver +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+// Copyright (c) 2018, Linaro, Limited. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for standalone MM driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for standalone MM driver." + diff --git a/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c new file mode 100644 index 000000000..70b4d10ef --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c @@ -0,0 +1,35 @@ +/** @file + MM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +EFI_MM_SYSTEM_TABLE *gMmst = NULL; + +/** + The constructor function caches the pointer of the MM Services Table. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param MmSystemTable A pointer to the MM System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +StandaloneMmServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + gMmst = MmSystemTable; + ASSERT (gMmst != NULL); + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf new file mode 100644 index 000000000..40f14aee6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf @@ -0,0 +1,34 @@ +## @file +# Standalone MM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = StandaloneMmServicesTableLib + MODULE_UNI_FILE = StandaloneMmServicesTableLib.uni + FILE_GUID = eaa4684f-fb4e-41f3-9967-307d5b409182 + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MmServicesTableLib|MM_STANDALONE + PI_SPECIFICATION_VERSION = 0x00010032 + CONSTRUCTOR = StandaloneMmServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + StandaloneMmServicesTableLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib diff --git a/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni new file mode 100644 index 000000000..79c4c2fde --- /dev/null +++ b/roms/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni @@ -0,0 +1,15 @@ +// /** @file +// +// Standalone MM Services Table Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Standalone MM Services Table Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Standalone MM Services Table Library." diff --git a/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c new file mode 100644 index 000000000..324e88c90 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c @@ -0,0 +1,115 @@ +/** @file + Entry point library instance to a UEFI application. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + + +/** + Entry point to UEFI Application. + + This function is the entry point for a UEFI Application. This function must call + ProcessLibraryConstructorList(), ProcessModuleEntryPointList(), and ProcessLibraryDestructorList(). + The return value from ProcessModuleEntryPointList() is returned. + If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than _gUefiDriverRevison, + then return EFI_INCOMPATIBLE_VERSION. + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The UEFI Application exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision. + @retval Other Return value from ProcessModuleEntryPointList(). + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (_gUefiDriverRevision != 0) { + // + // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the application. + // + if (SystemTable->Hdr.Revision < _gUefiDriverRevision) { + return EFI_INCOMPATIBLE_VERSION; + } + } + + // + // Call constructor for all libraries. + // + ProcessLibraryConstructorList (ImageHandle, SystemTable); + + // + // Call the module's entry point + // + Status = ProcessModuleEntryPointList (ImageHandle, SystemTable); + + // + // Process destructor for all libraries. + // + ProcessLibraryDestructorList (ImageHandle, SystemTable); + + // + // Return the return status code from the driver entry point + // + return Status; +} + + +/** + Invokes the library destructors for all dependent libraries and terminates + the UEFI Application. + + This function calls ProcessLibraryDestructorList() and the EFI Boot Service Exit() + with a status specified by Status. + + @param Status Status returned by the application that is exiting. + +**/ +VOID +EFIAPI +Exit ( + IN EFI_STATUS Status + ) + +{ + ProcessLibraryDestructorList (gImageHandle, gST); + + gBS->Exit (gImageHandle, Status, 0, NULL); +} + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The UEFI Application exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision. + @retval Other Return value from ProcessModuleEntryPointList(). + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return _ModuleEntryPoint (ImageHandle, SystemTable); +} diff --git a/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf new file mode 100644 index 000000000..b9d5b047a --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf @@ -0,0 +1,35 @@ +## @file +# Module entry point library for UEFI Application. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiApplicationEntryPoint + MODULE_UNI_FILE = UefiApplicationEntryPoint.uni + FILE_GUID = DADE8301-CB29-4fd5-8148-56FD246C5B88 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiApplicationEntryPoint|UEFI_APPLICATION + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + ApplicationEntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + DebugLib + BaseLib + diff --git a/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni new file mode 100644 index 000000000..8a68a8a70 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni @@ -0,0 +1,16 @@ +// /** @file +// Module entry point library for UEFI Application. +// +// Module entry point library for UEFI Application. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI Application" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI Application." + diff --git a/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c new file mode 100644 index 000000000..4fb6bc8fb --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c @@ -0,0 +1,60 @@ +/** @file + This library retrieve the EFI_BOOT_SERVICES pointer from EFI system table in + library's constructor. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include + +EFI_HANDLE gImageHandle = NULL; +EFI_SYSTEM_TABLE *gST = NULL; +EFI_BOOT_SERVICES *gBS = NULL; + +/** + The constructor function caches the pointer of Boot Services Table. + + The constructor function caches the pointer of Boot Services Table through System Table. + It will ASSERT() if the pointer of System Table is NULL. + It will ASSERT() if the pointer of Boot Services Table is NULL. + 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 +UefiBootServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache the Image Handle + // + gImageHandle = ImageHandle; + ASSERT (gImageHandle != NULL); + + // + // Cache pointer to the EFI System Table + // + gST = SystemTable; + ASSERT (gST != NULL); + + // + // Cache pointer to the EFI Boot Services Table + // + gBS = SystemTable->BootServices; + ASSERT (gBS != NULL); + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf new file mode 100644 index 000000000..3a17dc18f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf @@ -0,0 +1,35 @@ +## @file +# UEFI Boot Services Table Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiBootServicesTableLib + MODULE_UNI_FILE = UefiBootServicesTableLib.uni + FILE_GUID = ff5c7a2c-ab7a-4366-8616-11c6e53247b6 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiBootServicesTableLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = UefiBootServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiBootServicesTableLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni new file mode 100644 index 000000000..a7698f70b --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni @@ -0,0 +1,16 @@ +// /** @file +// UEFI Boot Services Table Library implementation. +// +// UEFI Boot Services Table Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI Boot Services Table Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "UEFI Boot Services Table Library implementation." + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c new file mode 100644 index 000000000..8ea38ea7c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c @@ -0,0 +1,374 @@ +/** @file + UEFI Debug Library that sends messages to the Console Output Device in the EFI System Table. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +// +// VA_LIST can not initialize to NULL for all compiler, so we use this to +// indicate a null VA_LIST +// +VA_LIST mVaListNull; + +extern BOOLEAN mPostEBS; +extern EFI_SYSTEM_TABLE *mDebugST; + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param ... A 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, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled base on Null-terminated format string and a + VA_LIST argument list or a BASE_LIST argument list. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +DebugPrintMarker ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, + IN BASE_LIST BaseListMarker + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + if (BaseListMarker == NULL) { + UnicodeVSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, VaListMarker); + } else { + UnicodeBSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, BaseListMarker); + } + + + // + // Send the print string to the Console Output device + // + if ((mDebugST != NULL) && (mDebugST->ConOut != NULL)) { + mDebugST->ConOut->OutputString (mDebugST->ConOut, Buffer); + } + } +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker); +} + + +/** + 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 The pointer to the name of the source file that generated + the assert condition. + @param LineNumber The line number in the source file that generated the + assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrintAsciiFormat ( + Buffer, + sizeof (Buffer), + "ASSERT [%a] %a(%d): %a\n", + gEfiCallerBaseName, + FileName, + LineNumber, + Description + ); + + // + // Send the print string to the Console Output device + // + if ((mDebugST != NULL) && (mDebugST->ConOut != NULL)) { + mDebugST->ConOut->OutputString (mDebugST->ConOut, Buffer); + } + + // + // 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 The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + 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/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLibConstructor.c b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLibConstructor.c new file mode 100644 index 000000000..b4ac17cf5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLibConstructor.c @@ -0,0 +1,99 @@ +/** @file + UEFI Dxe DebugLib constructor that prevent some debug service after ExitBootServices event, + because some pointer is nulled at that phase. + + Copyright (c) 2018, Microsoft Corporation + Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +// +// BOOLEAN value to indicate if it is at the post ExitBootServices pahse +// +BOOLEAN mPostEBS = FALSE; + +static EFI_EVENT mExitBootServicesEvent; + +// +// Pointer to SystemTable +// This library instance may have a cycle consume with UefiBootServicesTableLib +// because of the constructors. +// +EFI_SYSTEM_TABLE *mDebugST; + +/** + This routine sets the mPostEBS for exit boot servies true + to prevent DebugPort protocol dereferences when the pointer is nulled. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +ExitBootServicesCallback ( + EFI_EVENT Event, + VOID* Context + ) +{ + mPostEBS = TRUE; + return; +} + +/** + The constructor gets the pointers to the system table. + And create a event to indicate it is after ExitBootServices. + + @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 +DxeDebugLibConstructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mDebugST = SystemTable; + + SystemTable->BootServices->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + ExitBootServicesCallback, + NULL, + &mExitBootServicesEvent + ); + + return EFI_SUCCESS; +} + +/** + The destructor closes Exit Boot Services Event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeDebugLibDestructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (mExitBootServicesEvent != NULL) { + SystemTable->BootServices->CloseEvent (mExitBootServicesEvent); + } + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf new file mode 100644 index 000000000..53bbc8ce3 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf @@ -0,0 +1,53 @@ +## @file +# Instance of Debug Library using Console Output Device. +# +# Debug Lib that sends messages to the Console Output Device in the EFI System Table. +# +# Copyright (c) 2018, Microsoft Corporation +# +# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDebugLibConOut + MODULE_UNI_FILE = UefiDebugLibConOut.uni + FILE_GUID = 5cddfaf3-e9a7-4d16-bdce-1e002df475bb + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = DxeDebugLibConstructor + DESTRUCTOR = DxeDebugLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + DebugLib.c + DebugLibConstructor.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni new file mode 100644 index 000000000..48d462473 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Debug Library using Console Output Device. +// +// Debug Lib that sends messages to the Console Output Device in the EFI System Table. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Debug Library using Console Output Device" + +#string STR_MODULE_DESCRIPTION #language en-US "Debug Lib that sends messages to the Console Output Device in the EFI System Table." + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c new file mode 100644 index 000000000..cd7e2abbd --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c @@ -0,0 +1,429 @@ +/** @file + UEFI Debug Library that sends messages to EFI_DEBUGPORT_PROTOCOL.Write. + + Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +// +// Define the timeout for EFI_DEBUGPORT_PROTOCOL.Write +// +#define WRITE_TIMEOUT 1000 + + +EFI_DEBUGPORT_PROTOCOL *mDebugPort = NULL; + +// +// VA_LIST can not initialize to NULL for all compiler, so we use this to +// indicate a null VA_LIST +// +VA_LIST mVaListNull; + +extern BOOLEAN mPostEBS; +extern EFI_BOOT_SERVICES *mDebugBS; + +/** + Send message to DebugPort Protocol. + + If mDebugPort is NULL, i.e. EFI_DEBUGPORT_PROTOCOL is not located, + EFI_DEBUGPORT_PROTOCOL is located first. + Then, Buffer is sent via EFI_DEBUGPORT_PROTOCOL.Write. + + @param Buffer The message to be sent. + @param BufferLength The byte length of Buffer. +**/ +VOID +UefiDebugLibDebugPortProtocolWrite ( + IN CONST CHAR8 *Buffer, + IN UINTN BufferLength + ) +{ + UINTN Length; + EFI_STATUS Status; + + if (!mPostEBS) { + // + // If mDebugPort is NULL, initialize first. + // + if (mDebugPort == NULL) { + Status = mDebugBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&mDebugPort); + if (EFI_ERROR (Status)) { + return; + } + + mDebugPort->Reset (mDebugPort); + } + + // + // EFI_DEBUGPORT_PROTOCOL.Write is called until all message is sent. + // + while (BufferLength > 0) { + Length = BufferLength; + + Status = mDebugPort->Write (mDebugPort, WRITE_TIMEOUT, &Length, (VOID *) Buffer); + if (EFI_ERROR (Status) || BufferLength < Length) { + break; + } + + Buffer += Length; + BufferLength -= Length; + } + } +} + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param ... A 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, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled base on Null-terminated format string and a + VA_LIST argument list or a BASE_LIST argument list. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +DebugPrintMarker ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, + IN BASE_LIST BaseListMarker + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to an ASCII String + // + if (BaseListMarker == NULL) { + AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker); + } else { + AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker); + } + + // + // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write. + // + UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer)); + } +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker); +} + + +/** + 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 The pointer to the name of the source file that generated + the assert condition. + @param LineNumber The line number in the source file that generated the + assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // Generate the ASSERT() message in ASCII format + // + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "ASSERT [%a] %a(%d): %a\n", + gEfiCallerBaseName, + FileName, + LineNumber, + Description + ); + + // + // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write. + // + UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer)); + + // + // 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 The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + 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/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c new file mode 100644 index 000000000..96fc1c422 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c @@ -0,0 +1,99 @@ +/** @file + UEFI Dxe DebugLib constructor that prevent some debug service after ExitBootServices event, + because some pointer is nulled at that phase. + + Copyright (c) 2018, Microsoft Corporation + Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +// +// BOOLEAN value to indicate if it is at the post ExitBootServices pahse +// +BOOLEAN mPostEBS = FALSE; + +static EFI_EVENT mExitBootServicesEvent; + +// +// Pointer to SystemTable +// This library instance may have a cycle consume with UefiBootServicesTableLib +// because of the constructors. +// +EFI_BOOT_SERVICES *mDebugBS; + +/** + This routine sets the mPostEBS for exit boot servies true + to prevent DebugPort protocol dereferences when the pointer is nulled. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +ExitBootServicesCallback ( + EFI_EVENT Event, + VOID* Context + ) +{ + mPostEBS = TRUE; + return; +} + +/** + The constructor gets the pointers to boot services table. + And create a event to indicate it is after ExitBootServices. + + @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 +DxeDebugLibConstructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mDebugBS = SystemTable->BootServices; + + mDebugBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + ExitBootServicesCallback, + NULL, + &mExitBootServicesEvent + ); + + return EFI_SUCCESS; +} + +/** + The destructor closes Exit Boot Services Event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeDebugLibDestructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (mExitBootServicesEvent != NULL) { + SystemTable->BootServices->CloseEvent (mExitBootServicesEvent); + } + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf new file mode 100644 index 000000000..e12a1025c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf @@ -0,0 +1,56 @@ +## @file +# Instance of Debug Library using EFI_DEBUGPORT_PROTOCOL. +# +# Debug Lib that sends messages to EFI_DEBUGPORT_PROTOCOL.Write. +# +# Copyright (c) 2018, Microsoft Corporation +# +# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDebugLibDebugPortProtocol + MODULE_UNI_FILE = UefiDebugLibDebugPortProtocol.uni + FILE_GUID = 102287b4-6b12-4D41-91e1-ebee1f3aa614 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = DxeDebugLibConstructor + DESTRUCTOR = DxeDebugLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + DebugLib.c + DebugLibConstructor.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + DebugPrintErrorLevelLib + +[Protocols] + gEfiDebugPortProtocolGuid ## CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni new file mode 100644 index 000000000..d3de1f36e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Debug Library using EFI_DEBUGPORT_PROTOCOL. +// +// Debug Lib that sends messages to EFI_DEBUGPORT_PROTOCOL.Write. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Debug Library using EFI_DEBUGPORT_PROTOCOL" + +#string STR_MODULE_DESCRIPTION #language en-US "Debug Lib that sends messages to EFI_DEBUGPORT_PROTOCOL.Write." + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c new file mode 100644 index 000000000..fcfdafede --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c @@ -0,0 +1,375 @@ +/** @file + UEFI Debug Lib that sends messages to the Standard Error Device in the EFI System Table. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + + +// +// VA_LIST can not initialize to NULL for all compiler, so we use this to +// indicate a null VA_LIST +// +VA_LIST mVaListNull; + +extern BOOLEAN mPostEBS; +extern EFI_SYSTEM_TABLE *mDebugST; + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format The format string for the debug message to print. + @param ... The variable argument list whose contents are accessed + based on the format string specified by Format. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled base on Null-terminated format string and a + VA_LIST argument list or a BASE_LIST argument list. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +DebugPrintMarker ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker, + IN BASE_LIST BaseListMarker + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + if (BaseListMarker == NULL) { + UnicodeVSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, VaListMarker); + } else { + UnicodeBSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, BaseListMarker); + } + + // + // Send the print string to the Standard Error device + // + if ((mDebugST != NULL) && (mDebugST->StdErr != NULL)) { + mDebugST->StdErr->OutputString (mDebugST->StdErr, Buffer); + } + } +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param VaListMarker VA_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugVPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN VA_LIST VaListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL); +} + + +/** + Prints a debug message to the debug output device if the specified + error level is enabled. + This function use BASE_LIST which would provide a more compatible + service than VA_LIST. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and + the associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param BaseListMarker BASE_LIST marker for the variable argument list. + +**/ +VOID +EFIAPI +DebugBPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + IN BASE_LIST BaseListMarker + ) +{ + DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker); +} + + +/** + 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 The pointer to the name of the source file that generated + the assert condition. + @param LineNumber The line number in the source file that generated the + assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + if (!mPostEBS) { + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrintAsciiFormat ( + Buffer, + sizeof (Buffer), + "ASSERT [%a] %a(%d): %a\n", + gEfiCallerBaseName, + FileName, + LineNumber, + Description + ); + + // + // Send the print string to the Standard Error device + // + if ((mDebugST != NULL) && (mDebugST->StdErr != NULL)) { + mDebugST->StdErr->OutputString (mDebugST->StdErr, Buffer); + } + + // + // 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 The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + 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/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLibConstructor.c b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLibConstructor.c new file mode 100644 index 000000000..b4ac17cf5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLibConstructor.c @@ -0,0 +1,99 @@ +/** @file + UEFI Dxe DebugLib constructor that prevent some debug service after ExitBootServices event, + because some pointer is nulled at that phase. + + Copyright (c) 2018, Microsoft Corporation + Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +// +// BOOLEAN value to indicate if it is at the post ExitBootServices pahse +// +BOOLEAN mPostEBS = FALSE; + +static EFI_EVENT mExitBootServicesEvent; + +// +// Pointer to SystemTable +// This library instance may have a cycle consume with UefiBootServicesTableLib +// because of the constructors. +// +EFI_SYSTEM_TABLE *mDebugST; + +/** + This routine sets the mPostEBS for exit boot servies true + to prevent DebugPort protocol dereferences when the pointer is nulled. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +ExitBootServicesCallback ( + EFI_EVENT Event, + VOID* Context + ) +{ + mPostEBS = TRUE; + return; +} + +/** + The constructor gets the pointers to the system table. + And create a event to indicate it is after ExitBootServices. + + @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 +DxeDebugLibConstructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mDebugST = SystemTable; + + SystemTable->BootServices->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + ExitBootServicesCallback, + NULL, + &mExitBootServicesEvent + ); + + return EFI_SUCCESS; +} + +/** + The destructor closes Exit Boot Services Event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeDebugLibDestructor( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (mExitBootServicesEvent != NULL) { + SystemTable->BootServices->CloseEvent (mExitBootServicesEvent); + } + + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf new file mode 100644 index 000000000..5ecb971a0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf @@ -0,0 +1,51 @@ +## @file +# Instance of Debug Library using the Standard Error Device. +# +# Debug Lib that sends messages to the the Standard Error Device in the EFI System Table. +# +# Copyright (c) 2018, Microsoft Corporation +# +# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDebugLibStdErr + MODULE_UNI_FILE = UefiDebugLibStdErr.uni + FILE_GUID = b57a1df6-ffdb-4247-a3df-3a562176751a + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + + CONSTRUCTOR = DxeDebugLibConstructor + DESTRUCTOR = DxeDebugLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DebugLib.c + DebugLibConstructor.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni new file mode 100644 index 000000000..1748fb3ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Debug Library using the Standard Error Device. +// +// Debug Lib that sends messages to the the Standard Error Device in the EFI System Table. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Debug Library using the Standard Error Device" + +#string STR_MODULE_DESCRIPTION #language en-US "This Debug Lib sends messages to the Standard Error Device in the EFI System Table." + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c new file mode 100644 index 000000000..1515d2d59 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c @@ -0,0 +1,3666 @@ +/** @file + DevicePathFromText protocol as defined in the UEFI 2.0 specification. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +/** + + Duplicates a string. + + @param Src Source string. + + @return The duplicated string. + +**/ +CHAR16 * +UefiDevicePathLibStrDuplicate ( + IN CONST CHAR16 *Src + ) +{ + return AllocateCopyPool (StrSize (Src), Src); +} + +/** + + Get parameter in a pair of parentheses follow the given node name. + For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1". + + @param Str Device Path Text. + @param NodeName Name of the node. + + @return Parameter text for the node. + +**/ +CHAR16 * +GetParamByNodeName ( + IN CHAR16 *Str, + IN CHAR16 *NodeName + ) +{ + CHAR16 *ParamStr; + CHAR16 *StrPointer; + UINTN NodeNameLength; + UINTN ParameterLength; + + // + // Check whether the node name matchs + // + NodeNameLength = StrLen (NodeName); + if (StrnCmp (Str, NodeName, NodeNameLength) != 0) { + return NULL; + } + + ParamStr = Str + NodeNameLength; + if (!IS_LEFT_PARENTH (*ParamStr)) { + return NULL; + } + + // + // Skip the found '(' and find first occurrence of ')' + // + ParamStr++; + ParameterLength = 0; + StrPointer = ParamStr; + while (!IS_NULL (*StrPointer)) { + if (IS_RIGHT_PARENTH (*StrPointer)) { + break; + } + StrPointer++; + ParameterLength++; + } + if (IS_NULL (*StrPointer)) { + // + // ')' not found + // + return NULL; + } + + ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr); + if (ParamStr == NULL) { + return NULL; + } + // + // Terminate the parameter string + // + ParamStr[ParameterLength] = L'\0'; + + return ParamStr; +} + +/** + Gets current sub-string from a string list, before return + the list header is moved to next sub-string. The sub-string is separated + by the specified character. For example, the separator is ',', the string + list is "2,0,3", it returns "2", the remain list move to "0,3" + + @param List A string list separated by the specified separator + @param Separator The separator character + + @return A pointer to the current sub-string + +**/ +CHAR16 * +SplitStr ( + IN OUT CHAR16 **List, + IN CHAR16 Separator + ) +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + + Str = *List; + ReturnStr = Str; + + if (IS_NULL (*Str)) { + return ReturnStr; + } + + // + // Find first occurrence of the separator + // + while (!IS_NULL (*Str)) { + if (*Str == Separator) { + break; + } + Str++; + } + + if (*Str == Separator) { + // + // Find a sub-string, terminate it + // + *Str = L'\0'; + Str++; + } + + // + // Move to next sub-string + // + *List = Str; + + return ReturnStr; +} + +/** + Gets the next parameter string from the list. + + @param List A string list separated by the specified separator + + @return A pointer to the current sub-string + +**/ +CHAR16 * +GetNextParamStr ( + IN OUT CHAR16 **List + ) +{ + // + // The separator is comma + // + return SplitStr (List, L','); +} + +/** + Get one device node from entire device path text. + + @param DevicePath On input, the current Device Path node; on output, the next device path node + @param IsInstanceEnd This node is the end of a device path instance + + @return A device node text or NULL if no more device node available + +**/ +CHAR16 * +GetNextDeviceNodeStr ( + IN OUT CHAR16 **DevicePath, + OUT BOOLEAN *IsInstanceEnd + ) +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + UINTN ParenthesesStack; + + Str = *DevicePath; + if (IS_NULL (*Str)) { + return NULL; + } + + // + // Skip the leading '/', '(', ')' and ',' + // + while (!IS_NULL (*Str)) { + if (!IS_SLASH (*Str) && + !IS_COMMA (*Str) && + !IS_LEFT_PARENTH (*Str) && + !IS_RIGHT_PARENTH (*Str)) { + break; + } + Str++; + } + + ReturnStr = Str; + + // + // Scan for the separator of this device node, '/' or ',' + // + ParenthesesStack = 0; + while (!IS_NULL (*Str)) { + if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) { + break; + } + + if (IS_LEFT_PARENTH (*Str)) { + ParenthesesStack++; + } else if (IS_RIGHT_PARENTH (*Str)) { + ParenthesesStack--; + } + + Str++; + } + + if (ParenthesesStack != 0) { + // + // The '(' doesn't pair with ')', invalid device path text + // + return NULL; + } + + if (IS_COMMA (*Str)) { + *IsInstanceEnd = TRUE; + *Str = L'\0'; + Str++; + } else { + *IsInstanceEnd = FALSE; + if (!IS_NULL (*Str)) { + *Str = L'\0'; + Str++; + } + } + + *DevicePath = Str; + + return ReturnStr; +} + + +/** + Return whether the integer string is a hex string. + + @param Str The integer string + + @retval TRUE Hex string + @retval FALSE Decimal string + +**/ +BOOLEAN +IsHexStr ( + IN CHAR16 *Str + ) +{ + // + // skip preceeding white space + // + while ((*Str != 0) && *Str == L' ') { + Str ++; + } + // + // skip preceeding zeros + // + while ((*Str != 0) && *Str == L'0') { + Str ++; + } + + return (BOOLEAN) (*Str == L'x' || *Str == L'X'); +} + +/** + + Convert integer string to uint. + + @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal. + + @return A UINTN value represented by Str + +**/ +UINTN +Strtoi ( + IN CHAR16 *Str + ) +{ + if (IsHexStr (Str)) { + return StrHexToUintn (Str); + } else { + return StrDecimalToUintn (Str); + } +} + +/** + + Convert integer string to 64 bit data. + + @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal. + @param Data A pointer to the UINT64 value represented by Str + +**/ +VOID +Strtoi64 ( + IN CHAR16 *Str, + OUT UINT64 *Data + ) +{ + if (IsHexStr (Str)) { + *Data = StrHexToUint64 (Str); + } else { + *Data = StrDecimalToUint64 (Str); + } +} + +/** + Converts a Unicode string to ASCII string. + + @param Str The equivalent Unicode string + @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points + to the next ASCII string next to it + +**/ +VOID +StrToAscii ( + IN CHAR16 *Str, + IN OUT CHAR8 **AsciiStr + ) +{ + CHAR8 *Dest; + + Dest = *AsciiStr; + while (!IS_NULL (*Str)) { + *(Dest++) = (CHAR8) *(Str++); + } + *Dest = 0; + + // + // Return the string next to it + // + *AsciiStr = Dest + 1; +} + +/** + Converts a generic text device path node to device path structure. + + @param Type The type of the device path node. + @param TextDeviceNode The input text device path node. + + @return A pointer to device path structure. +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextGenericPath ( + IN UINT8 Type, + IN CHAR16 *TextDeviceNode + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + CHAR16 *SubtypeStr; + CHAR16 *DataStr; + UINTN DataLength; + + SubtypeStr = GetNextParamStr (&TextDeviceNode); + DataStr = GetNextParamStr (&TextDeviceNode); + + if (DataStr == NULL) { + DataLength = 0; + } else { + DataLength = StrLen (DataStr) / 2; + } + Node = CreateDeviceNode ( + Type, + (UINT8) Strtoi (SubtypeStr), + (UINT16) (sizeof (EFI_DEVICE_PATH_PROTOCOL) + DataLength) + ); + + StrHexToBytes (DataStr, DataLength * 2, (UINT8 *) (Node + 1), DataLength); + return Node; +} + +/** + Converts a generic text device path node to device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPath ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + + TypeStr = GetNextParamStr (&TextDeviceNode); + + return DevPathFromTextGenericPath ((UINT8) Strtoi (TypeStr), TextDeviceNode); +} + +/** + Converts a generic hardware text device path node to Hardware device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHardwarePath ( + IN CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (HARDWARE_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to Hardware PCI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware PCI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPci ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionStr; + CHAR16 *DeviceStr; + PCI_DEVICE_PATH *Pci; + + DeviceStr = GetNextParamStr (&TextDeviceNode); + FunctionStr = GetNextParamStr (&TextDeviceNode); + Pci = (PCI_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + (UINT16) sizeof (PCI_DEVICE_PATH) + ); + + Pci->Function = (UINT8) Strtoi (FunctionStr); + Pci->Device = (UINT8) Strtoi (DeviceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pci; +} + +/** + Converts a text device path node to Hardware PC card device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware PC card device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcCard ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionNumberStr; + PCCARD_DEVICE_PATH *Pccard; + + FunctionNumberStr = GetNextParamStr (&TextDeviceNode); + Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + (UINT16) sizeof (PCCARD_DEVICE_PATH) + ); + + Pccard->FunctionNumber = (UINT8) Strtoi (FunctionNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pccard; +} + +/** + Converts a text device path node to Hardware memory map device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware memory map device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMemoryMapped ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *MemoryTypeStr; + CHAR16 *StartingAddressStr; + CHAR16 *EndingAddressStr; + MEMMAP_DEVICE_PATH *MemMap; + + MemoryTypeStr = GetNextParamStr (&TextDeviceNode); + StartingAddressStr = GetNextParamStr (&TextDeviceNode); + EndingAddressStr = GetNextParamStr (&TextDeviceNode); + MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + (UINT16) sizeof (MEMMAP_DEVICE_PATH) + ); + + MemMap->MemoryType = (UINT32) Strtoi (MemoryTypeStr); + Strtoi64 (StartingAddressStr, &MemMap->StartingAddress); + Strtoi64 (EndingAddressStr, &MemMap->EndingAddress); + + return (EFI_DEVICE_PATH_PROTOCOL *) MemMap; +} + +/** + Converts a text device path node to Vendor device path structure based on the input Type + and SubType. + + @param TextDeviceNode The input Text device path node. + @param Type The type of device path node. + @param SubType The subtype of device path node. + + @return A pointer to the newly-created Vendor device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextVendor ( + IN CHAR16 *TextDeviceNode, + IN UINT8 Type, + IN UINT8 SubType + ) +{ + CHAR16 *GuidStr; + CHAR16 *DataStr; + UINTN Length; + VENDOR_DEVICE_PATH *Vendor; + + GuidStr = GetNextParamStr (&TextDeviceNode); + + DataStr = GetNextParamStr (&TextDeviceNode); + Length = StrLen (DataStr); + // + // Two hex characters make up 1 buffer byte + // + Length = (Length + 1) / 2; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + Type, + SubType, + (UINT16) (sizeof (VENDOR_DEVICE_PATH) + Length) + ); + + StrToGuid (GuidStr, &Vendor->Guid); + StrHexToBytes (DataStr, Length * 2, (UINT8 *) (Vendor + 1), Length); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor Hardware device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor Hardware device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenHw ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP + ); +} + +/** + Converts a text device path node to Hardware Controller device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Hardware Controller device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ControllerStr; + CONTROLLER_DEVICE_PATH *Controller; + + ControllerStr = GetNextParamStr (&TextDeviceNode); + Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + (UINT16) sizeof (CONTROLLER_DEVICE_PATH) + ); + Controller->ControllerNumber = (UINT32) Strtoi (ControllerStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Controller; +} + +/** + Converts a text device path node to BMC device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created BMC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBmc ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *InterfaceTypeStr; + CHAR16 *BaseAddressStr; + BMC_DEVICE_PATH *BmcDp; + + InterfaceTypeStr = GetNextParamStr (&TextDeviceNode); + BaseAddressStr = GetNextParamStr (&TextDeviceNode); + BmcDp = (BMC_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_BMC_DP, + (UINT16) sizeof (BMC_DEVICE_PATH) + ); + + BmcDp->InterfaceType = (UINT8) Strtoi (InterfaceTypeStr); + WriteUnaligned64 ( + (UINT64 *) (&BmcDp->BaseAddress), + StrHexToUint64 (BaseAddressStr) + ); + + return (EFI_DEVICE_PATH_PROTOCOL *) BmcDp; +} + +/** + Converts a generic ACPI text device path node to ACPI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to ACPI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiPath ( + IN CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (ACPI_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a string to EisaId. + + @param Text The input string. + + @return UINT32 EISA ID. +**/ +UINT32 +EisaIdFromText ( + IN CHAR16 *Text + ) +{ + return (((Text[0] - 'A' + 1) & 0x1f) << 10) + + (((Text[1] - 'A' + 1) & 0x1f) << 5) + + (((Text[2] - 'A' + 1) & 0x1f) << 0) + + (UINT32) (StrHexToUintn (&Text[3]) << 16) + ; +} + +/** + Converts a text device path node to ACPI HID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + HIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + (UINT16) sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = EisaIdFromText (HIDStr); + Acpi->UID = (UINT32) Strtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +/** + Converts a text device path node to ACPI HID device path structure. + + @param TextDeviceNode The input Text device path node. + @param PnPId The input plug and play identification. + + @return A pointer to the newly-created ACPI HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextAcpi ( + IN CHAR16 *TextDeviceNode, + IN UINT32 PnPId + ) +{ + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + (UINT16) sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = EFI_PNP_ID (PnPId); + Acpi->UID = (UINT32) Strtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +/** + Converts a text device path node to PCI root device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created PCI root device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPciRoot ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a03); +} + +/** + Converts a text device path node to PCIE root device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created PCIE root device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcieRoot ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a08); +} + +/** + Converts a text device path node to Floppy device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Floppy device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFloppy ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0604); +} + +/** + Converts a text device path node to Keyboard device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Keyboard device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextKeyboard ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0301); +} + +/** + Converts a text device path node to Serial device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSerial ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0501); +} + +/** + Converts a text device path node to Parallel Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Parallel Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextParallelPort ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0401); +} + +/** + Converts a text device path node to ACPI extension device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI extension device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiEx ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDStr; + CHAR16 *HIDSTRStr; + CHAR16 *CIDSTRStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + HIDSTRStr = GetNextParamStr (&TextDeviceNode); + CIDSTRStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + + Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (UIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (CIDSTRStr) + 1); + AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + AcpiEx->HID = EisaIdFromText (HIDStr); + AcpiEx->CID = EisaIdFromText (CIDStr); + AcpiEx->UID = (UINT32) Strtoi (UIDStr); + + AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)); + StrToAscii (HIDSTRStr, &AsciiStr); + StrToAscii (UIDSTRStr, &AsciiStr); + StrToAscii (CIDSTRStr, &AsciiStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx; +} + +/** + Converts a text device path node to ACPI extension device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI extension device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiExp ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3); + AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + AcpiEx->HID = EisaIdFromText (HIDStr); + // + // According to UEFI spec, the CID parametr is optional and has a default value of 0. + // So when the CID parametr is not specified or specified as 0 in the text device node. + // Set the CID to 0 in the ACPI extension device path structure. + // + if (*CIDStr == L'\0' || *CIDStr == L'0') { + AcpiEx->CID = 0; + } else { + AcpiEx->CID = EisaIdFromText (CIDStr); + } + AcpiEx->UID = 0; + + AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)); + // + // HID string is NULL + // + *AsciiStr = '\0'; + // + // Convert UID string + // + AsciiStr++; + StrToAscii (UIDSTRStr, &AsciiStr); + // + // CID string is NULL + // + *AsciiStr = '\0'; + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx; +} + +/** + Converts a text device path node to ACPI _ADR device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI _ADR device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiAdr ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *DisplayDeviceStr; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + UINTN Index; + UINTN Length; + + AcpiAdr = (ACPI_ADR_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + (UINT16) sizeof (ACPI_ADR_DEVICE_PATH) + ); + ASSERT (AcpiAdr != NULL); + + for (Index = 0; ; Index++) { + DisplayDeviceStr = GetNextParamStr (&TextDeviceNode); + if (IS_NULL (*DisplayDeviceStr)) { + break; + } + if (Index > 0) { + Length = DevicePathNodeLength (AcpiAdr); + AcpiAdr = ReallocatePool ( + Length, + Length + sizeof (UINT32), + AcpiAdr + ); + ASSERT (AcpiAdr != NULL); + SetDevicePathNodeLength (AcpiAdr, Length + sizeof (UINT32)); + } + + (&AcpiAdr->ADR)[Index] = (UINT32) Strtoi (DisplayDeviceStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr; +} + +/** + Converts a generic messaging text device path node to messaging device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to messaging device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMsg ( + IN CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (MESSAGING_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to Parallel Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Parallel Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAta ( +IN CHAR16 *TextDeviceNode +) +{ + CHAR16 *PrimarySecondaryStr; + CHAR16 *SlaveMasterStr; + CHAR16 *LunStr; + ATAPI_DEVICE_PATH *Atapi; + + Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + (UINT16) sizeof (ATAPI_DEVICE_PATH) + ); + + PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode); + SlaveMasterStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + + if (StrCmp (PrimarySecondaryStr, L"Primary") == 0) { + Atapi->PrimarySecondary = 0; + } else if (StrCmp (PrimarySecondaryStr, L"Secondary") == 0) { + Atapi->PrimarySecondary = 1; + } else { + Atapi->PrimarySecondary = (UINT8) Strtoi (PrimarySecondaryStr); + } + if (StrCmp (SlaveMasterStr, L"Master") == 0) { + Atapi->SlaveMaster = 0; + } else if (StrCmp (SlaveMasterStr, L"Slave") == 0) { + Atapi->SlaveMaster = 1; + } else { + Atapi->SlaveMaster = (UINT8) Strtoi (SlaveMasterStr); + } + + Atapi->Lun = (UINT16) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Atapi; +} + +/** + Converts a text device path node to SCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextScsi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + SCSI_DEVICE_PATH *Scsi; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + (UINT16) sizeof (SCSI_DEVICE_PATH) + ); + + Scsi->Pun = (UINT16) Strtoi (PunStr); + Scsi->Lun = (UINT16) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Scsi; +} + +/** + Converts a text device path node to Fibre device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Fibre device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibre ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNEL_DEVICE_PATH *Fibre; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + (UINT16) sizeof (FIBRECHANNEL_DEVICE_PATH) + ); + + Fibre->Reserved = 0; + Strtoi64 (WWNStr, &Fibre->WWN); + Strtoi64 (LunStr, &Fibre->Lun); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fibre; +} + +/** + Converts a text device path node to FibreEx device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created FibreEx device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibreEx ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNELEX_DEVICE_PATH *FibreEx; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + FibreEx = (FIBRECHANNELEX_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNELEX_DP, + (UINT16) sizeof (FIBRECHANNELEX_DEVICE_PATH) + ); + + FibreEx->Reserved = 0; + Strtoi64 (WWNStr, (UINT64 *) (&FibreEx->WWN)); + Strtoi64 (LunStr, (UINT64 *) (&FibreEx->Lun)); + + *(UINT64 *) (&FibreEx->WWN) = SwapBytes64 (*(UINT64 *) (&FibreEx->WWN)); + *(UINT64 *) (&FibreEx->Lun) = SwapBytes64 (*(UINT64 *) (&FibreEx->Lun)); + + return (EFI_DEVICE_PATH_PROTOCOL *) FibreEx; +} + +/** + Converts a text device path node to 1394 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created 1394 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromText1394 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + F1394_DEVICE_PATH *F1394DevPath; + + GuidStr = GetNextParamStr (&TextDeviceNode); + F1394DevPath = (F1394_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + (UINT16) sizeof (F1394_DEVICE_PATH) + ); + + F1394DevPath->Reserved = 0; + F1394DevPath->Guid = StrHexToUint64 (GuidStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) F1394DevPath; +} + +/** + Converts a text device path node to USB device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsb ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PortStr; + CHAR16 *InterfaceStr; + USB_DEVICE_PATH *Usb; + + PortStr = GetNextParamStr (&TextDeviceNode); + InterfaceStr = GetNextParamStr (&TextDeviceNode); + Usb = (USB_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + (UINT16) sizeof (USB_DEVICE_PATH) + ); + + Usb->ParentPortNumber = (UINT8) Strtoi (PortStr); + Usb->InterfaceNumber = (UINT8) Strtoi (InterfaceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Usb; +} + +/** + Converts a text device path node to I20 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created I20 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextI2O ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TIDStr; + I2O_DEVICE_PATH *I2ODevPath; + + TIDStr = GetNextParamStr (&TextDeviceNode); + I2ODevPath = (I2O_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + (UINT16) sizeof (I2O_DEVICE_PATH) + ); + + I2ODevPath->Tid = (UINT32) Strtoi (TIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) I2ODevPath; +} + +/** + Converts a text device path node to Infini Band device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Infini Band device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextInfiniband ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FlagsStr; + CHAR16 *GuidStr; + CHAR16 *SidStr; + CHAR16 *TidStr; + CHAR16 *DidStr; + INFINIBAND_DEVICE_PATH *InfiniBand; + + FlagsStr = GetNextParamStr (&TextDeviceNode); + GuidStr = GetNextParamStr (&TextDeviceNode); + SidStr = GetNextParamStr (&TextDeviceNode); + TidStr = GetNextParamStr (&TextDeviceNode); + DidStr = GetNextParamStr (&TextDeviceNode); + InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + (UINT16) sizeof (INFINIBAND_DEVICE_PATH) + ); + + InfiniBand->ResourceFlags = (UINT32) Strtoi (FlagsStr); + StrToGuid (GuidStr, (EFI_GUID *) InfiniBand->PortGid); + Strtoi64 (SidStr, &InfiniBand->ServiceId); + Strtoi64 (TidStr, &InfiniBand->TargetPortId); + Strtoi64 (DidStr, &InfiniBand->DeviceId); + + return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand; +} + +/** + Converts a text device path node to Vendor-Defined Messaging device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor-Defined Messaging device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMsg ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP + ); +} + +/** + Converts a text device path node to Vendor defined PC-ANSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined PC-ANSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenPcAnsi ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined VT100 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined VT100 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined VT100 Plus device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined VT100 Plus device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100Plus ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined UTF8 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined UTF8 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenUtf8 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to UART Flow Control device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UART Flow Control device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUartFlowCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ValueStr; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + + ValueStr = GetNextParamStr (&TextDeviceNode); + UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (UART_FLOW_CONTROL_DEVICE_PATH) + ); + + CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid); + if (StrCmp (ValueStr, L"XonXoff") == 0) { + UartFlowControl->FlowControlMap = 2; + } else if (StrCmp (ValueStr, L"Hardware") == 0) { + UartFlowControl->FlowControlMap = 1; + } else { + UartFlowControl->FlowControlMap = 0; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl; +} + +/** + Converts a text device path node to Serial Attached SCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial Attached SCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSAS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + CHAR16 *ReservedStr; + UINT16 Info; + UINT16 Uint16; + SAS_DEVICE_PATH *Sas; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + ReservedStr = GetNextParamStr (&TextDeviceNode); + Sas = (SAS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (SAS_DEVICE_PATH) + ); + + CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid); + Strtoi64 (AddressStr, &Sas->SasAddress); + Strtoi64 (LunStr, &Sas->Lun); + Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr); + + if (StrCmp (SASSATAStr, L"NoTopology") == 0) { + Info = 0x0; + + } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) { + + Uint16 = (UINT16) Strtoi (DriveBayStr); + if (Uint16 == 0) { + Info = 0x1; + } else { + Info = (UINT16) (0x2 | ((Uint16 - 1) << 8)); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= BIT4; + } + + // + // Location is an integer between 0 and 1 or else + // the keyword Internal (0) or External (1). + // + if (StrCmp (LocationStr, L"External") == 0) { + Uint16 = 1; + } else if (StrCmp (LocationStr, L"Internal") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0); + } + Info |= (Uint16 << 5); + + // + // Connect is an integer between 0 and 3 or else + // the keyword Direct (0) or Expanded (1). + // + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Uint16 = 1; + } else if (StrCmp (ConnectStr, L"Direct") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1)); + } + Info |= (Uint16 << 6); + + } else { + Info = (UINT16) Strtoi (SASSATAStr); + } + + Sas->DeviceTopology = Info; + Sas->Reserved = (UINT32) Strtoi (ReservedStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sas; +} + +/** + Converts a text device path node to Serial Attached SCSI Ex device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial Attached SCSI Ex device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSasEx ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + UINT16 Info; + UINT16 Uint16; + UINT64 SasAddress; + UINT64 Lun; + SASEX_DEVICE_PATH *SasEx; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + SasEx = (SASEX_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SASEX_DP, + (UINT16) sizeof (SASEX_DEVICE_PATH) + ); + + Strtoi64 (AddressStr, &SasAddress); + Strtoi64 (LunStr, &Lun); + WriteUnaligned64 ((UINT64 *) &SasEx->SasAddress, SwapBytes64 (SasAddress)); + WriteUnaligned64 ((UINT64 *) &SasEx->Lun, SwapBytes64 (Lun)); + SasEx->RelativeTargetPort = (UINT16) Strtoi (RTPStr); + + if (StrCmp (SASSATAStr, L"NoTopology") == 0) { + Info = 0x0; + + } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) { + + Uint16 = (UINT16) Strtoi (DriveBayStr); + if (Uint16 == 0) { + Info = 0x1; + } else { + Info = (UINT16) (0x2 | ((Uint16 - 1) << 8)); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= BIT4; + } + + // + // Location is an integer between 0 and 1 or else + // the keyword Internal (0) or External (1). + // + if (StrCmp (LocationStr, L"External") == 0) { + Uint16 = 1; + } else if (StrCmp (LocationStr, L"Internal") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0); + } + Info |= (Uint16 << 5); + + // + // Connect is an integer between 0 and 3 or else + // the keyword Direct (0) or Expanded (1). + // + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Uint16 = 1; + } else if (StrCmp (ConnectStr, L"Direct") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1)); + } + Info |= (Uint16 << 6); + + } else { + Info = (UINT16) Strtoi (SASSATAStr); + } + + SasEx->DeviceTopology = Info; + + return (EFI_DEVICE_PATH_PROTOCOL *) SasEx; +} + +/** + Converts a text device path node to NVM Express Namespace device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created NVM Express Namespace device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextNVMe ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *NamespaceIdStr; + CHAR16 *NamespaceUuidStr; + NVME_NAMESPACE_DEVICE_PATH *Nvme; + UINT8 *Uuid; + UINTN Index; + + NamespaceIdStr = GetNextParamStr (&TextDeviceNode); + NamespaceUuidStr = GetNextParamStr (&TextDeviceNode); + Nvme = (NVME_NAMESPACE_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_NVME_NAMESPACE_DP, + (UINT16) sizeof (NVME_NAMESPACE_DEVICE_PATH) + ); + + Nvme->NamespaceId = (UINT32) Strtoi (NamespaceIdStr); + Uuid = (UINT8 *) &Nvme->NamespaceUuid; + + Index = sizeof (Nvme->NamespaceUuid) / sizeof (UINT8); + while (Index-- != 0) { + Uuid[Index] = (UINT8) StrHexToUintn (SplitStr (&NamespaceUuidStr, L'-')); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Nvme; +} + +/** + Converts a text device path node to UFS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UFS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUfs ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + UFS_DEVICE_PATH *Ufs; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Ufs = (UFS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UFS_DP, + (UINT16) sizeof (UFS_DEVICE_PATH) + ); + + Ufs->Pun = (UINT8) Strtoi (PunStr); + Ufs->Lun = (UINT8) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Ufs; +} + +/** + Converts a text device path node to SD (Secure Digital) device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SD device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSd ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SlotNumberStr; + SD_DEVICE_PATH *Sd; + + SlotNumberStr = GetNextParamStr (&TextDeviceNode); + Sd = (SD_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SD_DP, + (UINT16) sizeof (SD_DEVICE_PATH) + ); + + Sd->SlotNumber = (UINT8) Strtoi (SlotNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sd; +} + +/** + Converts a text device path node to EMMC (Embedded MMC) device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created EMMC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextEmmc ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SlotNumberStr; + EMMC_DEVICE_PATH *Emmc; + + SlotNumberStr = GetNextParamStr (&TextDeviceNode); + Emmc = (EMMC_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_EMMC_DP, + (UINT16) sizeof (EMMC_DEVICE_PATH) + ); + + Emmc->SlotNumber = (UINT8) Strtoi (SlotNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Emmc; +} + +/** + Converts a text device path node to Debug Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Debug Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDebugPort ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vend; + + Vend = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH) + ); + + CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vend; +} + +/** + Converts a text device path node to MAC device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created MAC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMAC ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *IfTypeStr; + UINTN Length; + MAC_ADDR_DEVICE_PATH *MACDevPath; + + AddressStr = GetNextParamStr (&TextDeviceNode); + IfTypeStr = GetNextParamStr (&TextDeviceNode); + MACDevPath = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + (UINT16) sizeof (MAC_ADDR_DEVICE_PATH) + ); + + MACDevPath->IfType = (UINT8) Strtoi (IfTypeStr); + + Length = sizeof (EFI_MAC_ADDRESS); + if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) { + Length = 6; + } + + StrHexToBytes (AddressStr, Length * 2, MACDevPath->MacAddress.Addr, Length); + + return (EFI_DEVICE_PATH_PROTOCOL *) MACDevPath; +} + + +/** + Converts a text format to the network protocol ID. + + @param Text String of protocol field. + + @return Network protocol ID . + +**/ +UINTN +NetworkProtocolFromText ( + IN CHAR16 *Text + ) +{ + if (StrCmp (Text, L"UDP") == 0) { + return RFC_1700_UDP_PROTOCOL; + } + + if (StrCmp (Text, L"TCP") == 0) { + return RFC_1700_TCP_PROTOCOL; + } + + return Strtoi (Text); +} + + +/** + Converts a text device path node to IPV4 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created IPV4 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv4 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + CHAR16 *GatewayIPStr; + CHAR16 *SubnetMaskStr; + IPv4_DEVICE_PATH *IPv4; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + GatewayIPStr = GetNextParamStr (&TextDeviceNode); + SubnetMaskStr = GetNextParamStr (&TextDeviceNode); + IPv4 = (IPv4_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + (UINT16) sizeof (IPv4_DEVICE_PATH) + ); + + StrToIpv4Address (RemoteIPStr, NULL, &IPv4->RemoteIpAddress, NULL); + IPv4->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv4->StaticIpAddress = TRUE; + } else { + IPv4->StaticIpAddress = FALSE; + } + + StrToIpv4Address (LocalIPStr, NULL, &IPv4->LocalIpAddress, NULL); + if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) { + StrToIpv4Address (GatewayIPStr, NULL, &IPv4->GatewayIpAddress, NULL); + StrToIpv4Address (SubnetMaskStr, NULL, &IPv4->SubnetMask, NULL); + } else { + ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress)); + ZeroMem (&IPv4->SubnetMask, sizeof (IPv4->SubnetMask)); + } + + IPv4->LocalPort = 0; + IPv4->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv4; +} + +/** + Converts a text device path node to IPV6 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created IPV6 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv6 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + CHAR16 *GatewayIPStr; + CHAR16 *PrefixLengthStr; + IPv6_DEVICE_PATH *IPv6; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + PrefixLengthStr = GetNextParamStr (&TextDeviceNode); + GatewayIPStr = GetNextParamStr (&TextDeviceNode); + IPv6 = (IPv6_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + (UINT16) sizeof (IPv6_DEVICE_PATH) + ); + + StrToIpv6Address (RemoteIPStr, NULL, &IPv6->RemoteIpAddress, NULL); + IPv6->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv6->IpAddressOrigin = 0; + } else if (StrCmp (TypeStr, L"StatelessAutoConfigure") == 0) { + IPv6->IpAddressOrigin = 1; + } else { + IPv6->IpAddressOrigin = 2; + } + + StrToIpv6Address (LocalIPStr, NULL, &IPv6->LocalIpAddress, NULL); + if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) { + StrToIpv6Address (GatewayIPStr, NULL, &IPv6->GatewayIpAddress, NULL); + IPv6->PrefixLength = (UINT8) Strtoi (PrefixLengthStr); + } else { + ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress)); + IPv6->PrefixLength = 0; + } + + IPv6->LocalPort = 0; + IPv6->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv6; +} + +/** + Converts a text device path node to UART device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UART device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUart ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BaudStr; + CHAR16 *DataBitsStr; + CHAR16 *ParityStr; + CHAR16 *StopBitsStr; + UART_DEVICE_PATH *Uart; + + BaudStr = GetNextParamStr (&TextDeviceNode); + DataBitsStr = GetNextParamStr (&TextDeviceNode); + ParityStr = GetNextParamStr (&TextDeviceNode); + StopBitsStr = GetNextParamStr (&TextDeviceNode); + Uart = (UART_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + (UINT16) sizeof (UART_DEVICE_PATH) + ); + + if (StrCmp (BaudStr, L"DEFAULT") == 0) { + Uart->BaudRate = 115200; + } else { + Strtoi64 (BaudStr, &Uart->BaudRate); + } + Uart->DataBits = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Strtoi (DataBitsStr)); + switch (*ParityStr) { + case L'D': + Uart->Parity = 0; + break; + + case L'N': + Uart->Parity = 1; + break; + + case L'E': + Uart->Parity = 2; + break; + + case L'O': + Uart->Parity = 3; + break; + + case L'M': + Uart->Parity = 4; + break; + + case L'S': + Uart->Parity = 5; + break; + + default: + Uart->Parity = (UINT8) Strtoi (ParityStr); + break; + } + + if (StrCmp (StopBitsStr, L"D") == 0) { + Uart->StopBits = (UINT8) 0; + } else if (StrCmp (StopBitsStr, L"1") == 0) { + Uart->StopBits = (UINT8) 1; + } else if (StrCmp (StopBitsStr, L"1.5") == 0) { + Uart->StopBits = (UINT8) 2; + } else if (StrCmp (StopBitsStr, L"2") == 0) { + Uart->StopBits = (UINT8) 3; + } else { + Uart->StopBits = (UINT8) Strtoi (StopBitsStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uart; +} + +/** + Converts a text device path node to USB class device path structure. + + @param TextDeviceNode The input Text device path node. + @param UsbClassText A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text. + + @return A pointer to the newly-created USB class device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextUsbClass ( + IN CHAR16 *TextDeviceNode, + IN USB_CLASS_TEXT *UsbClassText + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *ClassStr; + CHAR16 *SubClassStr; + CHAR16 *ProtocolStr; + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + (UINT16) sizeof (USB_CLASS_DEVICE_PATH) + ); + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + if (UsbClassText->ClassExist) { + ClassStr = GetNextParamStr (&TextDeviceNode); + if (*ClassStr == L'\0') { + UsbClass->DeviceClass = 0xFF; + } else { + UsbClass->DeviceClass = (UINT8) Strtoi (ClassStr); + } + } else { + UsbClass->DeviceClass = UsbClassText->Class; + } + if (UsbClassText->SubClassExist) { + SubClassStr = GetNextParamStr (&TextDeviceNode); + if (*SubClassStr == L'\0') { + UsbClass->DeviceSubClass = 0xFF; + } else { + UsbClass->DeviceSubClass = (UINT8) Strtoi (SubClassStr); + } + } else { + UsbClass->DeviceSubClass = UsbClassText->SubClass; + } + + ProtocolStr = GetNextParamStr (&TextDeviceNode); + + if (*VIDStr == L'\0') { + UsbClass->VendorId = 0xFFFF; + } else { + UsbClass->VendorId = (UINT16) Strtoi (VIDStr); + } + if (*PIDStr == L'\0') { + UsbClass->ProductId = 0xFFFF; + } else { + UsbClass->ProductId = (UINT16) Strtoi (PIDStr); + } + if (*ProtocolStr == L'\0') { + UsbClass->DeviceProtocol = 0xFF; + } else { + UsbClass->DeviceProtocol = (UINT8) Strtoi (ProtocolStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass; +} + + +/** + Converts a text device path node to USB class device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB class device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbClass ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = TRUE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB audio device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB audio device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbAudio ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_AUDIO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB CDC Control device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB CDC Control device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCControl ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCCONTROL; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB HID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHID ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HID; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB Image device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB Image device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbImage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_IMAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB Print device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB Print device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbPrinter ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_PRINTER; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB mass storage device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB mass storage device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbMassStorage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_MASS_STORAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB HUB device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB HUB device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHub ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HUB; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB CDC data device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB CDC data device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCData ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCDATA; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB smart card device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB smart card device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbSmartCard ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_SMART_CARD; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB video device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB video device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbVideo ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_VIDEO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB diagnostic device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB diagnostic device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDiagnostic ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_DIAGNOSTIC; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB wireless device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB wireless device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWireless ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_WIRELESS; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB device firmware update device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB device firmware update device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDeviceFirmwareUpdate ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB IRDA bridge device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB IRDA bridge device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbIrdaBridge ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB text and measurement device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB text and measurement device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbTestAndMeasurement ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_TEST; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB WWID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB WWID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWwid ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *InterfaceNumStr; + CHAR16 *SerialNumberStr; + USB_WWID_DEVICE_PATH *UsbWwid; + UINTN SerialNumberStrLen; + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + InterfaceNumStr = GetNextParamStr (&TextDeviceNode); + SerialNumberStr = GetNextParamStr (&TextDeviceNode); + SerialNumberStrLen = StrLen (SerialNumberStr); + if (SerialNumberStrLen >= 2 && + SerialNumberStr[0] == L'\"' && + SerialNumberStr[SerialNumberStrLen - 1] == L'\"' + ) { + SerialNumberStr[SerialNumberStrLen - 1] = L'\0'; + SerialNumberStr++; + SerialNumberStrLen -= 2; + } + UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + (UINT16) (sizeof (USB_WWID_DEVICE_PATH) + SerialNumberStrLen * sizeof (CHAR16)) + ); + UsbWwid->VendorId = (UINT16) Strtoi (VIDStr); + UsbWwid->ProductId = (UINT16) Strtoi (PIDStr); + UsbWwid->InterfaceNumber = (UINT16) Strtoi (InterfaceNumStr); + + // + // There is no memory allocated in UsbWwid for the '\0' in SerialNumberStr. + // Therefore, the '\0' will not be copied. + // + CopyMem ( + (UINT8 *) UsbWwid + sizeof (USB_WWID_DEVICE_PATH), + SerialNumberStr, + SerialNumberStrLen * sizeof (CHAR16) + ); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid; +} + +/** + Converts a text device path node to Logic Unit device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Logic Unit device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUnit ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *LunStr; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LunStr = GetNextParamStr (&TextDeviceNode); + LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + (UINT16) sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH) + ); + + LogicalUnit->Lun = (UINT8) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit; +} + +/** + Converts a text device path node to iSCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created iSCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextiSCSI ( + IN CHAR16 *TextDeviceNode + ) +{ + UINT16 Options; + CHAR16 *NameStr; + CHAR16 *PortalGroupStr; + CHAR16 *LunStr; + CHAR16 *HeaderDigestStr; + CHAR16 *DataDigestStr; + CHAR16 *AuthenticationStr; + CHAR16 *ProtocolStr; + CHAR8 *AsciiStr; + ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath; + UINT64 Lun; + + NameStr = GetNextParamStr (&TextDeviceNode); + PortalGroupStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + HeaderDigestStr = GetNextParamStr (&TextDeviceNode); + DataDigestStr = GetNextParamStr (&TextDeviceNode); + AuthenticationStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + ISCSIDevPath = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + (UINT16) (sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr)) + ); + + AsciiStr = ISCSIDevPath->TargetName; + StrToAscii (NameStr, &AsciiStr); + + ISCSIDevPath->TargetPortalGroupTag = (UINT16) Strtoi (PortalGroupStr); + Strtoi64 (LunStr, &Lun); + WriteUnaligned64 ((UINT64 *) &ISCSIDevPath->Lun, SwapBytes64 (Lun)); + + Options = 0x0000; + if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) { + Options |= 0x0002; + } + + if (StrCmp (DataDigestStr, L"CRC32C") == 0) { + Options |= 0x0008; + } + + if (StrCmp (AuthenticationStr, L"None") == 0) { + Options |= 0x0800; + } + + if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) { + Options |= 0x1000; + } + + ISCSIDevPath->LoginOption = (UINT16) Options; + + if (IS_NULL (*ProtocolStr) || (StrCmp (ProtocolStr, L"TCP") == 0)) { + ISCSIDevPath->NetworkProtocol = 0; + } else { + // + // Undefined and reserved. + // + ISCSIDevPath->NetworkProtocol = 1; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) ISCSIDevPath; +} + +/** + Converts a text device path node to VLAN device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created VLAN device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVlan ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VlanStr; + VLAN_DEVICE_PATH *Vlan; + + VlanStr = GetNextParamStr (&TextDeviceNode); + Vlan = (VLAN_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VLAN_DP, + (UINT16) sizeof (VLAN_DEVICE_PATH) + ); + + Vlan->VlanId = (UINT16) Strtoi (VlanStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vlan; +} + +/** + Converts a text device path node to Bluetooth device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Bluetooth device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBluetooth ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BluetoothStr; + BLUETOOTH_DEVICE_PATH *BluetoothDp; + + BluetoothStr = GetNextParamStr (&TextDeviceNode); + BluetoothDp = (BLUETOOTH_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_BLUETOOTH_DP, + (UINT16) sizeof (BLUETOOTH_DEVICE_PATH) + ); + StrHexToBytes ( + BluetoothStr, + sizeof (BLUETOOTH_ADDRESS) * 2, + BluetoothDp->BD_ADDR.Address, + sizeof (BLUETOOTH_ADDRESS) + ); + return (EFI_DEVICE_PATH_PROTOCOL *) BluetoothDp; +} + +/** + Converts a text device path node to Wi-Fi device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Wi-Fi device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextWiFi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SSIdStr; + CHAR8 AsciiStr[33]; + UINTN DataLen; + WIFI_DEVICE_PATH *WiFiDp; + + SSIdStr = GetNextParamStr (&TextDeviceNode); + WiFiDp = (WIFI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_WIFI_DP, + (UINT16) sizeof (WIFI_DEVICE_PATH) + ); + + if (NULL != SSIdStr) { + DataLen = StrLen (SSIdStr); + if (StrLen (SSIdStr) > 32) { + SSIdStr[32] = L'\0'; + DataLen = 32; + } + + UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr)); + CopyMem (WiFiDp->SSId, AsciiStr, DataLen); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) WiFiDp; +} + +/** + Converts a text device path node to Bluetooth LE device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Bluetooth LE device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBluetoothLE ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BluetoothLeAddrStr; + CHAR16 *BluetoothLeAddrTypeStr; + BLUETOOTH_LE_DEVICE_PATH *BluetoothLeDp; + + BluetoothLeAddrStr = GetNextParamStr (&TextDeviceNode); + BluetoothLeAddrTypeStr = GetNextParamStr (&TextDeviceNode); + BluetoothLeDp = (BLUETOOTH_LE_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_BLUETOOTH_LE_DP, + (UINT16) sizeof (BLUETOOTH_LE_DEVICE_PATH) + ); + + BluetoothLeDp->Address.Type = (UINT8) Strtoi (BluetoothLeAddrTypeStr); + StrHexToBytes ( + BluetoothLeAddrStr, sizeof (BluetoothLeDp->Address.Address) * 2, + BluetoothLeDp->Address.Address, sizeof (BluetoothLeDp->Address.Address) + ); + return (EFI_DEVICE_PATH_PROTOCOL *) BluetoothLeDp; +} + +/** + Converts a text device path node to DNS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created DNS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDns ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *DeviceNodeStr; + CHAR16 *DeviceNodeStrPtr; + UINT32 DnsServerIpCount; + UINT16 DnsDeviceNodeLength; + DNS_DEVICE_PATH *DnsDeviceNode; + UINT32 DnsServerIpIndex; + CHAR16 *DnsServerIp; + + + // + // Count the DNS server address number. + // + DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode); + if (DeviceNodeStr == NULL) { + return NULL; + } + + DeviceNodeStrPtr = DeviceNodeStr; + + DnsServerIpCount = 0; + while (DeviceNodeStrPtr != NULL && *DeviceNodeStrPtr != L'\0') { + GetNextParamStr (&DeviceNodeStrPtr); + DnsServerIpCount ++; + } + + FreePool (DeviceNodeStr); + DeviceNodeStr = NULL; + + // + // One or more instances of the DNS server address in EFI_IP_ADDRESS, + // otherwise, NULL will be returned. + // + if (DnsServerIpCount == 0) { + return NULL; + } + + // + // Create the DNS DeviceNode. + // + DnsDeviceNodeLength = (UINT16) (sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (UINT8) + DnsServerIpCount * sizeof (EFI_IP_ADDRESS)); + DnsDeviceNode = (DNS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DNS_DP, + DnsDeviceNodeLength + ); + if (DnsDeviceNode == NULL) { + return NULL; + } + + // + // Confirm the DNS server address is IPv4 or IPv6 type. + // + DeviceNodeStrPtr = TextDeviceNode; + while (!IS_NULL (*DeviceNodeStrPtr)) { + if (*DeviceNodeStrPtr == L'.') { + DnsDeviceNode->IsIPv6 = 0x00; + break; + } + + if (*DeviceNodeStrPtr == L':') { + DnsDeviceNode->IsIPv6 = 0x01; + break; + } + + DeviceNodeStrPtr++; + } + + for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) { + DnsServerIp = GetNextParamStr (&TextDeviceNode); + if (DnsDeviceNode->IsIPv6 == 0x00) { + StrToIpv4Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v4), NULL); + } else { + StrToIpv6Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v6), NULL); + } + } + + return (EFI_DEVICE_PATH_PROTOCOL *) DnsDeviceNode; +} + +/** + Converts a text device path node to URI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created URI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUri ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *UriStr; + UINTN UriLength; + URI_DEVICE_PATH *Uri; + + UriStr = GetNextParamStr (&TextDeviceNode); + UriLength = StrnLenS (UriStr, MAX_UINT16 - sizeof (URI_DEVICE_PATH)); + Uri = (URI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_URI_DP, + (UINT16) (sizeof (URI_DEVICE_PATH) + UriLength) + ); + + while (UriLength-- != 0) { + Uri->Uri[UriLength] = (CHAR8) UriStr[UriLength]; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uri; +} + +/** + Converts a media text device path node to media device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to media device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMediaPath ( + IN CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (MEDIA_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to HD device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created HD device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHD ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PartitionStr; + CHAR16 *TypeStr; + CHAR16 *SignatureStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + UINT32 Signature32; + HARDDRIVE_DEVICE_PATH *Hd; + + PartitionStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + SignatureStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + (UINT16) sizeof (HARDDRIVE_DEVICE_PATH) + ); + + Hd->PartitionNumber = (UINT32) Strtoi (PartitionStr); + + ZeroMem (Hd->Signature, 16); + Hd->MBRType = (UINT8) 0; + + if (StrCmp (TypeStr, L"MBR") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_MBR; + Hd->MBRType = 0x01; + + Signature32 = (UINT32) Strtoi (SignatureStr); + CopyMem (Hd->Signature, &Signature32, sizeof (UINT32)); + } else if (StrCmp (TypeStr, L"GPT") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_GUID; + Hd->MBRType = 0x02; + + StrToGuid (SignatureStr, (EFI_GUID *) Hd->Signature); + } else { + Hd->SignatureType = (UINT8) Strtoi (TypeStr); + } + + Strtoi64 (StartStr, &Hd->PartitionStart); + Strtoi64 (SizeStr, &Hd->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) Hd; +} + +/** + Converts a text device path node to CDROM device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created CDROM device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCDROM ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *EntryStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + CDROM_DEVICE_PATH *CDROMDevPath; + + EntryStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + CDROMDevPath = (CDROM_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + (UINT16) sizeof (CDROM_DEVICE_PATH) + ); + + CDROMDevPath->BootEntry = (UINT32) Strtoi (EntryStr); + Strtoi64 (StartStr, &CDROMDevPath->PartitionStart); + Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) CDROMDevPath; +} + +/** + Converts a text device path node to Vendor-defined media device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor-defined media device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMedia ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP + ); +} + +/** + Converts a text device path node to File device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created File device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFilePath ( + IN CHAR16 *TextDeviceNode + ) +{ + FILEPATH_DEVICE_PATH *File; + + File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + (UINT16) (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2) + ); + + StrCpyS (File->PathName, StrLen (TextDeviceNode) + 1, TextDeviceNode); + + return (EFI_DEVICE_PATH_PROTOCOL *) File; +} + +/** + Converts a text device path node to Media protocol device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Media protocol device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMedia ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_PROTOCOL_DEVICE_PATH *Media; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Media = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + (UINT16) sizeof (MEDIA_PROTOCOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Media->Protocol); + + return (EFI_DEVICE_PATH_PROTOCOL *) Media; +} + +/** + Converts a text device path node to firmware volume device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created firmware volume device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFv ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_FW_VOL_DEVICE_PATH *Fv; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Fv = (MEDIA_FW_VOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + (UINT16) sizeof (MEDIA_FW_VOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Fv->FvName); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fv; +} + +/** + Converts a text device path node to firmware file device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created firmware file device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFvFile ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile; + + GuidStr = GetNextParamStr (&TextDeviceNode); + FvFile = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_FILE_DP, + (UINT16) sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &FvFile->FvFileName); + + return (EFI_DEVICE_PATH_PROTOCOL *) FvFile; +} + +/** + Converts a text device path node to text relative offset device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextRelativeOffsetRange ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingOffsetStr; + CHAR16 *EndingOffsetStr; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + StartingOffsetStr = GetNextParamStr (&TextDeviceNode); + EndingOffsetStr = GetNextParamStr (&TextDeviceNode); + Offset = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RELATIVE_OFFSET_RANGE_DP, + (UINT16) sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH) + ); + + Strtoi64 (StartingOffsetStr, &Offset->StartingOffset); + Strtoi64 (EndingOffsetStr, &Offset->EndingOffset); + + return (EFI_DEVICE_PATH_PROTOCOL *) Offset; +} + +/** + Converts a text device path node to text ram disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextRamDisk ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *TypeGuidStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + TypeGuidStr = GetNextParamStr (&TextDeviceNode); + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + StrToGuid (TypeGuidStr, &RamDisk->TypeGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text virtual disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVirtualDisk ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text virtual cd device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVirtualCd ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text persistent virtual disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPersistentVirtualDisk ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text persistent virtual cd device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPersistentVirtualCd ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a BBS text device path node to BBS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to BBS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBbsPath ( + IN CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (BBS_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to BIOS Boot Specification device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created BIOS Boot Specification device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBBS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + CHAR16 *IdStr; + CHAR16 *FlagsStr; + CHAR8 *AsciiStr; + BBS_BBS_DEVICE_PATH *Bbs; + + TypeStr = GetNextParamStr (&TextDeviceNode); + IdStr = GetNextParamStr (&TextDeviceNode); + FlagsStr = GetNextParamStr (&TextDeviceNode); + Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode ( + BBS_DEVICE_PATH, + BBS_BBS_DP, + (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr)) + ); + + if (StrCmp (TypeStr, L"Floppy") == 0) { + Bbs->DeviceType = BBS_TYPE_FLOPPY; + } else if (StrCmp (TypeStr, L"HD") == 0) { + Bbs->DeviceType = BBS_TYPE_HARDDRIVE; + } else if (StrCmp (TypeStr, L"CDROM") == 0) { + Bbs->DeviceType = BBS_TYPE_CDROM; + } else if (StrCmp (TypeStr, L"PCMCIA") == 0) { + Bbs->DeviceType = BBS_TYPE_PCMCIA; + } else if (StrCmp (TypeStr, L"USB") == 0) { + Bbs->DeviceType = BBS_TYPE_USB; + } else if (StrCmp (TypeStr, L"Network") == 0) { + Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK; + } else { + Bbs->DeviceType = (UINT16) Strtoi (TypeStr); + } + + AsciiStr = Bbs->String; + StrToAscii (IdStr, &AsciiStr); + + Bbs->StatusFlag = (UINT16) Strtoi (FlagsStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Bbs; +} + +/** + Converts a text device path node to SATA device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SATA device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSata ( + IN CHAR16 *TextDeviceNode + ) +{ + SATA_DEVICE_PATH *Sata; + CHAR16 *Param1; + CHAR16 *Param2; + CHAR16 *Param3; + + Param1 = GetNextParamStr (&TextDeviceNode); + Param2 = GetNextParamStr (&TextDeviceNode); + Param3 = GetNextParamStr (&TextDeviceNode); + + Sata = (SATA_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SATA_DP, + (UINT16) sizeof (SATA_DEVICE_PATH) + ); + Sata->HBAPortNumber = (UINT16) Strtoi (Param1); + + // + // According to UEFI spec, if PMPN is not provided, the default is 0xFFFF + // + if (*Param2 == L'\0' ) { + Sata->PortMultiplierPortNumber = 0xFFFF; + } else { + Sata->PortMultiplierPortNumber = (UINT16) Strtoi (Param2); + } + Sata->Lun = (UINT16) Strtoi (Param3); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sata; +} + +GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE mUefiDevicePathLibDevPathFromTextTable[] = { + {L"Path", DevPathFromTextPath }, + + {L"HardwarePath", DevPathFromTextHardwarePath }, + {L"Pci", DevPathFromTextPci }, + {L"PcCard", DevPathFromTextPcCard }, + {L"MemoryMapped", DevPathFromTextMemoryMapped }, + {L"VenHw", DevPathFromTextVenHw }, + {L"Ctrl", DevPathFromTextCtrl }, + {L"BMC", DevPathFromTextBmc }, + + {L"AcpiPath", DevPathFromTextAcpiPath }, + {L"Acpi", DevPathFromTextAcpi }, + {L"PciRoot", DevPathFromTextPciRoot }, + {L"PcieRoot", DevPathFromTextPcieRoot }, + {L"Floppy", DevPathFromTextFloppy }, + {L"Keyboard", DevPathFromTextKeyboard }, + {L"Serial", DevPathFromTextSerial }, + {L"ParallelPort", DevPathFromTextParallelPort }, + {L"AcpiEx", DevPathFromTextAcpiEx }, + {L"AcpiExp", DevPathFromTextAcpiExp }, + {L"AcpiAdr", DevPathFromTextAcpiAdr }, + + {L"Msg", DevPathFromTextMsg }, + {L"Ata", DevPathFromTextAta }, + {L"Scsi", DevPathFromTextScsi }, + {L"Fibre", DevPathFromTextFibre }, + {L"FibreEx", DevPathFromTextFibreEx }, + {L"I1394", DevPathFromText1394 }, + {L"USB", DevPathFromTextUsb }, + {L"I2O", DevPathFromTextI2O }, + {L"Infiniband", DevPathFromTextInfiniband }, + {L"VenMsg", DevPathFromTextVenMsg }, + {L"VenPcAnsi", DevPathFromTextVenPcAnsi }, + {L"VenVt100", DevPathFromTextVenVt100 }, + {L"VenVt100Plus", DevPathFromTextVenVt100Plus }, + {L"VenUtf8", DevPathFromTextVenUtf8 }, + {L"UartFlowCtrl", DevPathFromTextUartFlowCtrl }, + {L"SAS", DevPathFromTextSAS }, + {L"SasEx", DevPathFromTextSasEx }, + {L"NVMe", DevPathFromTextNVMe }, + {L"UFS", DevPathFromTextUfs }, + {L"SD", DevPathFromTextSd }, + {L"eMMC", DevPathFromTextEmmc }, + {L"DebugPort", DevPathFromTextDebugPort }, + {L"MAC", DevPathFromTextMAC }, + {L"IPv4", DevPathFromTextIPv4 }, + {L"IPv6", DevPathFromTextIPv6 }, + {L"Uart", DevPathFromTextUart }, + {L"UsbClass", DevPathFromTextUsbClass }, + {L"UsbAudio", DevPathFromTextUsbAudio }, + {L"UsbCDCControl", DevPathFromTextUsbCDCControl }, + {L"UsbHID", DevPathFromTextUsbHID }, + {L"UsbImage", DevPathFromTextUsbImage }, + {L"UsbPrinter", DevPathFromTextUsbPrinter }, + {L"UsbMassStorage", DevPathFromTextUsbMassStorage }, + {L"UsbHub", DevPathFromTextUsbHub }, + {L"UsbCDCData", DevPathFromTextUsbCDCData }, + {L"UsbSmartCard", DevPathFromTextUsbSmartCard }, + {L"UsbVideo", DevPathFromTextUsbVideo }, + {L"UsbDiagnostic", DevPathFromTextUsbDiagnostic }, + {L"UsbWireless", DevPathFromTextUsbWireless }, + {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate }, + {L"UsbIrdaBridge", DevPathFromTextUsbIrdaBridge }, + {L"UsbTestAndMeasurement", DevPathFromTextUsbTestAndMeasurement }, + {L"UsbWwid", DevPathFromTextUsbWwid }, + {L"Unit", DevPathFromTextUnit }, + {L"iSCSI", DevPathFromTextiSCSI }, + {L"Vlan", DevPathFromTextVlan }, + {L"Dns", DevPathFromTextDns }, + {L"Uri", DevPathFromTextUri }, + {L"Bluetooth", DevPathFromTextBluetooth }, + {L"Wi-Fi", DevPathFromTextWiFi }, + {L"BluetoothLE", DevPathFromTextBluetoothLE }, + {L"MediaPath", DevPathFromTextMediaPath }, + {L"HD", DevPathFromTextHD }, + {L"CDROM", DevPathFromTextCDROM }, + {L"VenMedia", DevPathFromTextVenMedia }, + {L"Media", DevPathFromTextMedia }, + {L"Fv", DevPathFromTextFv }, + {L"FvFile", DevPathFromTextFvFile }, + {L"Offset", DevPathFromTextRelativeOffsetRange }, + {L"RamDisk", DevPathFromTextRamDisk }, + {L"VirtualDisk", DevPathFromTextVirtualDisk }, + {L"VirtualCD", DevPathFromTextVirtualCd }, + {L"PersistentVirtualDisk", DevPathFromTextPersistentVirtualDisk }, + {L"PersistentVirtualCD", DevPathFromTextPersistentVirtualCd }, + + {L"BbsPath", DevPathFromTextBbsPath }, + {L"BBS", DevPathFromTextBBS }, + {L"Sata", DevPathFromTextSata }, + {NULL, NULL} +}; + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +{ + DEVICE_PATH_FROM_TEXT FromText; + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + CHAR16 *DeviceNodeStr; + UINTN Index; + + if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) { + return NULL; + } + + ParamStr = NULL; + FromText = NULL; + DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode); + ASSERT (DeviceNodeStr != NULL); + + for (Index = 0; mUefiDevicePathLibDevPathFromTextTable[Index].Function != NULL; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, mUefiDevicePathLibDevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + FromText = mUefiDevicePathLibDevPathFromTextTable[Index].Function; + break; + } + } + + if (FromText == NULL) { + // + // A file path + // + FromText = DevPathFromTextFilePath; + DeviceNode = FromText (DeviceNodeStr); + } else { + DeviceNode = FromText (ParamStr); + FreePool (ParamStr); + } + + FreePool (DeviceNodeStr); + + return DeviceNode; +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + CHAR16 *DevicePathStr; + CHAR16 *Str; + CHAR16 *DeviceNodeStr; + BOOLEAN IsInstanceEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) { + return NULL; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + ASSERT (DevicePath != NULL); + SetDevicePathEndNode (DevicePath); + + DevicePathStr = UefiDevicePathLibStrDuplicate (TextDevicePath); + + Str = DevicePathStr; + while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) { + DeviceNode = UefiDevicePathLibConvertTextToDeviceNode (DeviceNodeStr); + + NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode); + FreePool (DevicePath); + FreePool (DeviceNode); + DevicePath = NewDevicePath; + + if (IsInstanceEnd) { + DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + ASSERT (DeviceNode != NULL); + SetDevicePathEndNode (DeviceNode); + DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode); + FreePool (DevicePath); + FreePool (DeviceNode); + DevicePath = NewDevicePath; + } + } + + FreePool (DevicePathStr); + return DevicePath; +} diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c new file mode 100644 index 000000000..fb65ebd8f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c @@ -0,0 +1,2455 @@ +/** @file + DevicePathToText protocol as defined in the UEFI 2.0 specification. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +/** + Concatenates a formatted unicode string to 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 ... Variable arguments based on the format string. + + @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 +UefiDevicePathLibCatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ) +{ + UINTN Count; + VA_LIST Args; + + VA_START (Args, Fmt); + Count = SPrintLength (Fmt, Args); + VA_END(Args); + + if ((Str->Count + (Count + 1)) * sizeof (CHAR16) > Str->Capacity) { + Str->Capacity = (Str->Count + (Count + 1) * 2) * sizeof (CHAR16); + Str->Str = ReallocatePool ( + Str->Count * sizeof (CHAR16), + Str->Capacity, + Str->Str + ); + ASSERT (Str->Str != NULL); + } + VA_START (Args, Fmt); + UnicodeVSPrint (&Str->Str[Str->Count], Str->Capacity - Str->Count * sizeof (CHAR16), Fmt, Args); + Str->Count += Count; + + VA_END (Args); + return Str->Str; +} + +/** + Converts a PCI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + UefiDevicePathLibCatPrint (Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function); +} + +/** + Converts a PC Card device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + UefiDevicePathLibCatPrint (Str, L"PcCard(0x%x)", Pccard->FunctionNumber); +} + +/** + Converts a Memory Map device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"MemoryMapped(0x%x,0x%lx,0x%lx)", + MemMap->MemoryType, + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +/** + Converts a Vendor device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + UINTN Index; + UINTN DataLength; + UINT32 FlowControlMap; + UINT16 Info; + + Vendor = (VENDOR_DEVICE_PATH *) DevPath; + switch (DevicePathType (&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: + Type = L"Hw"; + break; + + case MESSAGING_DEVICE_PATH: + Type = L"Msg"; + if (AllowShortcuts) { + if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) { + UefiDevicePathLibCatPrint (Str, L"VenPcAnsi()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) { + UefiDevicePathLibCatPrint (Str, L"VenVt100()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) { + UefiDevicePathLibCatPrint (Str, L"VenVt100Plus()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) { + UefiDevicePathLibCatPrint (Str, L"VenUtf8()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid)) { + FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap); + switch (FlowControlMap & 0x00000003) { + case 0: + UefiDevicePathLibCatPrint (Str, L"UartFlowCtrl(%s)", L"None"); + break; + + case 1: + UefiDevicePathLibCatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); + break; + + case 2: + UefiDevicePathLibCatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); + break; + + default: + break; + } + + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) { + UefiDevicePathLibCatPrint ( + Str, + L"SAS(0x%lx,0x%lx,0x%x,", + ((SAS_DEVICE_PATH *) Vendor)->SasAddress, + ((SAS_DEVICE_PATH *) Vendor)->Lun, + ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort + ); + Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology); + if (((Info & 0x0f) == 0) && ((Info & BIT7) == 0)) { + UefiDevicePathLibCatPrint (Str, L"NoTopology,0,0,0,"); + } else if (((Info & 0x0f) <= 2) && ((Info & BIT7) == 0)) { + UefiDevicePathLibCatPrint ( + Str, + L"%s,%s,%s,", + ((Info & BIT4) != 0) ? L"SATA" : L"SAS", + ((Info & BIT5) != 0) ? L"External" : L"Internal", + ((Info & BIT6) != 0) ? L"Expanded" : L"Direct" + ); + if ((Info & 0x0f) == 1) { + UefiDevicePathLibCatPrint (Str, L"0,"); + } else { + // + // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256 + // + UefiDevicePathLibCatPrint (Str, L"0x%x,", ((Info >> 8) & 0xff) + 1); + } + } else { + UefiDevicePathLibCatPrint (Str, L"0x%x,0,0,0,", Info); + } + + UefiDevicePathLibCatPrint (Str, L"0x%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) { + UefiDevicePathLibCatPrint (Str, L"DebugPort()"); + return ; + } + } + break; + + case MEDIA_DEVICE_PATH: + Type = L"Media"; + break; + + default: + Type = L"?"; + break; + } + + DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); + UefiDevicePathLibCatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid); + if (DataLength != 0) { + UefiDevicePathLibCatPrint (Str, L","); + for (Index = 0; Index < DataLength; Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); + } + } + + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts a Controller device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"Ctrl(0x%x)", + Controller->ControllerNumber + ); +} + +/** + Converts a BMC device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextBmc ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BMC_DEVICE_PATH *Bmc; + + Bmc = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"BMC(0x%x,0x%lx)", + Bmc->InterfaceType, + ReadUnaligned64 ((UINT64 *) (&Bmc->BaseAddress)) + ); +} + +/** + Converts a ACPI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM (Acpi->HID)) { + case 0x0a03: + UefiDevicePathLibCatPrint (Str, L"PciRoot(0x%x)", Acpi->UID); + break; + + case 0x0a08: + UefiDevicePathLibCatPrint (Str, L"PcieRoot(0x%x)", Acpi->UID); + break; + + case 0x0604: + UefiDevicePathLibCatPrint (Str, L"Floppy(0x%x)", Acpi->UID); + break; + + case 0x0301: + UefiDevicePathLibCatPrint (Str, L"Keyboard(0x%x)", Acpi->UID); + break; + + case 0x0501: + UefiDevicePathLibCatPrint (Str, L"Serial(0x%x)", Acpi->UID); + break; + + case 0x0401: + UefiDevicePathLibCatPrint (Str, L"ParallelPort(0x%x)", Acpi->UID); + break; + + default: + UefiDevicePathLibCatPrint (Str, L"Acpi(PNP%04x,0x%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID); + break; + } + } else { + UefiDevicePathLibCatPrint (Str, L"Acpi(0x%08x,0x%x)", Acpi->HID, Acpi->UID); + } +} + +/** + Converts a ACPI extended HID device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextAcpiEx ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; + CHAR8 *HIDStr; + CHAR8 *UIDStr; + CHAR8 *CIDStr; + CHAR16 HIDText[11]; + CHAR16 CIDText[11]; + + AcpiEx = DevPath; + HIDStr = (CHAR8 *) (((UINT8 *) AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)); + UIDStr = HIDStr + AsciiStrLen (HIDStr) + 1; + CIDStr = UIDStr + AsciiStrLen (UIDStr) + 1; + + if (DisplayOnly) { + if ((EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A03) || + (EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A03 && EISA_ID_TO_NUM (AcpiEx->HID) != 0x0A08)) { + if (AcpiEx->UID == 0) { + UefiDevicePathLibCatPrint (Str, L"PciRoot(%a)", UIDStr); + } else { + UefiDevicePathLibCatPrint (Str, L"PciRoot(0x%x)", AcpiEx->UID); + } + return; + } + + if (EISA_ID_TO_NUM (AcpiEx->HID) == 0x0A08 || EISA_ID_TO_NUM (AcpiEx->CID) == 0x0A08) { + if (AcpiEx->UID == 0) { + UefiDevicePathLibCatPrint (Str, L"PcieRoot(%a)", UIDStr); + } else { + UefiDevicePathLibCatPrint (Str, L"PcieRoot(0x%x)", AcpiEx->UID); + } + return; + } + } + + // + // Converts EISA identification to string. + // + UnicodeSPrint ( + HIDText, + sizeof (HIDText), + L"%c%c%c%04X", + ((AcpiEx->HID >> 10) & 0x1f) + 'A' - 1, + ((AcpiEx->HID >> 5) & 0x1f) + 'A' - 1, + ((AcpiEx->HID >> 0) & 0x1f) + 'A' - 1, + (AcpiEx->HID >> 16) & 0xFFFF + ); + UnicodeSPrint ( + CIDText, + sizeof (CIDText), + L"%c%c%c%04X", + ((AcpiEx->CID >> 10) & 0x1f) + 'A' - 1, + ((AcpiEx->CID >> 5) & 0x1f) + 'A' - 1, + ((AcpiEx->CID >> 0) & 0x1f) + 'A' - 1, + (AcpiEx->CID >> 16) & 0xFFFF + ); + + if ((*HIDStr == '\0') && (*CIDStr == '\0') && (*UIDStr != '\0')) { + // + // use AcpiExp() + // + if (AcpiEx->CID == 0) { + UefiDevicePathLibCatPrint ( + Str, + L"AcpiExp(%s,0,%a)", + HIDText, + UIDStr + ); + } else { + UefiDevicePathLibCatPrint ( + Str, + L"AcpiExp(%s,%s,%a)", + HIDText, + CIDText, + UIDStr + ); + } + } else { + if (DisplayOnly) { + // + // display only + // + if (AcpiEx->HID == 0) { + UefiDevicePathLibCatPrint (Str, L"AcpiEx(%a,", HIDStr); + } else { + UefiDevicePathLibCatPrint (Str, L"AcpiEx(%s,", HIDText); + } + + if (AcpiEx->CID == 0) { + UefiDevicePathLibCatPrint (Str, L"%a,", CIDStr); + } else { + UefiDevicePathLibCatPrint (Str, L"%s,", CIDText); + } + + if (AcpiEx->UID == 0) { + UefiDevicePathLibCatPrint (Str, L"%a)", UIDStr); + } else { + UefiDevicePathLibCatPrint (Str, L"0x%x)", AcpiEx->UID); + } + } else { + UefiDevicePathLibCatPrint ( + Str, + L"AcpiEx(%s,%s,0x%x,%a,%a,%a)", + HIDText, + CIDText, + AcpiEx->UID, + HIDStr, + CIDStr, + UIDStr + ); + } + } +} + +/** + Converts a ACPI address device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextAcpiAdr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_ADR_DEVICE_PATH *AcpiAdr; + UINT16 Index; + UINT16 Length; + UINT16 AdditionalAdrCount; + + AcpiAdr = DevPath; + Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr); + AdditionalAdrCount = (UINT16) ((Length - 8) / 4); + + UefiDevicePathLibCatPrint (Str, L"AcpiAdr(0x%x", AcpiAdr->ADR); + for (Index = 0; Index < AdditionalAdrCount; Index++) { + UefiDevicePathLibCatPrint (Str, L",0x%x", *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4)); + } + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts a ATAPI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + + if (DisplayOnly) { + UefiDevicePathLibCatPrint (Str, L"Ata(0x%x)", Atapi->Lun); + } else { + UefiDevicePathLibCatPrint ( + Str, + L"Ata(%s,%s,0x%x)", + (Atapi->PrimarySecondary == 1) ? L"Secondary" : L"Primary", + (Atapi->SlaveMaster == 1) ? L"Slave" : L"Master", + Atapi->Lun + ); + } +} + +/** + Converts a SCSI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + UefiDevicePathLibCatPrint (Str, L"Scsi(0x%x,0x%x)", Scsi->Pun, Scsi->Lun); +} + +/** + Converts a Fibre device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + UefiDevicePathLibCatPrint (Str, L"Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun); +} + +/** + Converts a FibreEx device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextFibreEx ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FIBRECHANNELEX_DEVICE_PATH *FibreEx; + UINTN Index; + + FibreEx = DevPath; + UefiDevicePathLibCatPrint (Str, L"FibreEx(0x"); + for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", FibreEx->WWN[Index]); + } + UefiDevicePathLibCatPrint (Str, L",0x"); + for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", FibreEx->Lun[Index]); + } + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts a Sas Ex device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextSasEx ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SASEX_DEVICE_PATH *SasEx; + UINTN Index; + + SasEx = DevPath; + UefiDevicePathLibCatPrint (Str, L"SasEx(0x"); + + for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", SasEx->SasAddress[Index]); + } + UefiDevicePathLibCatPrint (Str, L",0x"); + for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", SasEx->Lun[Index]); + } + UefiDevicePathLibCatPrint (Str, L",0x%x,", SasEx->RelativeTargetPort); + + if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) { + UefiDevicePathLibCatPrint (Str, L"NoTopology,0,0,0"); + } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) { + UefiDevicePathLibCatPrint ( + Str, + L"%s,%s,%s,", + ((SasEx->DeviceTopology & BIT4) != 0) ? L"SATA" : L"SAS", + ((SasEx->DeviceTopology & BIT5) != 0) ? L"External" : L"Internal", + ((SasEx->DeviceTopology & BIT6) != 0) ? L"Expanded" : L"Direct" + ); + if ((SasEx->DeviceTopology & 0x0f) == 1) { + UefiDevicePathLibCatPrint (Str, L"0"); + } else { + // + // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256 + // + UefiDevicePathLibCatPrint (Str, L"0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1); + } + } else { + UefiDevicePathLibCatPrint (Str, L"0x%x,0,0,0", SasEx->DeviceTopology); + } + + UefiDevicePathLibCatPrint (Str, L")"); + return ; + +} + +/** + Converts a NVM Express Namespace device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextNVMe ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + NVME_NAMESPACE_DEVICE_PATH *Nvme; + UINT8 *Uuid; + + Nvme = DevPath; + Uuid = (UINT8 *) &Nvme->NamespaceUuid; + UefiDevicePathLibCatPrint ( + Str, + L"NVMe(0x%x,%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)", + Nvme->NamespaceId, + Uuid[7], Uuid[6], Uuid[5], Uuid[4], + Uuid[3], Uuid[2], Uuid[1], Uuid[0] + ); +} + +/** + Converts a UFS device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUfs ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + UFS_DEVICE_PATH *Ufs; + + Ufs = DevPath; + UefiDevicePathLibCatPrint (Str, L"UFS(0x%x,0x%x)", Ufs->Pun, Ufs->Lun); +} + +/** + Converts a SD (Secure Digital) device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextSd ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SD_DEVICE_PATH *Sd; + + Sd = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"SD(0x%x)", + Sd->SlotNumber + ); +} + +/** + Converts a EMMC (Embedded MMC) device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextEmmc ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + EMMC_DEVICE_PATH *Emmc; + + Emmc = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"eMMC(0x%x)", + Emmc->SlotNumber + ); +} + +/** + Converts a 1394 device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToText1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + F1394_DEVICE_PATH *F1394DevPath; + + F1394DevPath = DevPath; + // + // Guid has format of IEEE-EUI64 + // + UefiDevicePathLibCatPrint (Str, L"I1394(%016lx)", F1394DevPath->Guid); +} + +/** + Converts a USB device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + UefiDevicePathLibCatPrint (Str, L"USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber); +} + +/** + Converts a USB WWID device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUsbWWID ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_WWID_DEVICE_PATH *UsbWWId; + CHAR16 *SerialNumberStr; + CHAR16 *NewStr; + UINT16 Length; + + UsbWWId = DevPath; + + SerialNumberStr = (CHAR16 *) ((UINT8 *) UsbWWId + sizeof (USB_WWID_DEVICE_PATH)); + Length = (UINT16) ((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16)); + if (Length >= 1 && SerialNumberStr [Length - 1] != 0) { + // + // In case no NULL terminator in SerialNumber, create a new one with NULL terminator + // + NewStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), SerialNumberStr); + ASSERT (NewStr != NULL); + NewStr [Length] = 0; + SerialNumberStr = NewStr; + } + + UefiDevicePathLibCatPrint ( + Str, + L"UsbWwid(0x%x,0x%x,0x%x,\"%s\")", + UsbWWId->VendorId, + UsbWWId->ProductId, + UsbWWId->InterfaceNumber, + SerialNumberStr + ); +} + +/** + Converts a Logic Unit device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextLogicalUnit ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LogicalUnit = DevPath; + UefiDevicePathLibCatPrint (Str, L"Unit(0x%x)", LogicalUnit->Lun); +} + +/** + Converts a USB class device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUsbClass ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_CLASS_DEVICE_PATH *UsbClass; + BOOLEAN IsKnownSubClass; + + + UsbClass = DevPath; + + IsKnownSubClass = TRUE; + switch (UsbClass->DeviceClass) { + case USB_CLASS_AUDIO: + UefiDevicePathLibCatPrint (Str, L"UsbAudio"); + break; + + case USB_CLASS_CDCCONTROL: + UefiDevicePathLibCatPrint (Str, L"UsbCDCControl"); + break; + + case USB_CLASS_HID: + UefiDevicePathLibCatPrint (Str, L"UsbHID"); + break; + + case USB_CLASS_IMAGE: + UefiDevicePathLibCatPrint (Str, L"UsbImage"); + break; + + case USB_CLASS_PRINTER: + UefiDevicePathLibCatPrint (Str, L"UsbPrinter"); + break; + + case USB_CLASS_MASS_STORAGE: + UefiDevicePathLibCatPrint (Str, L"UsbMassStorage"); + break; + + case USB_CLASS_HUB: + UefiDevicePathLibCatPrint (Str, L"UsbHub"); + break; + + case USB_CLASS_CDCDATA: + UefiDevicePathLibCatPrint (Str, L"UsbCDCData"); + break; + + case USB_CLASS_SMART_CARD: + UefiDevicePathLibCatPrint (Str, L"UsbSmartCard"); + break; + + case USB_CLASS_VIDEO: + UefiDevicePathLibCatPrint (Str, L"UsbVideo"); + break; + + case USB_CLASS_DIAGNOSTIC: + UefiDevicePathLibCatPrint (Str, L"UsbDiagnostic"); + break; + + case USB_CLASS_WIRELESS: + UefiDevicePathLibCatPrint (Str, L"UsbWireless"); + break; + + default: + IsKnownSubClass = FALSE; + break; + } + + if (IsKnownSubClass) { + UefiDevicePathLibCatPrint ( + Str, + L"(0x%x,0x%x,0x%x,0x%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + return; + } + + if (UsbClass->DeviceClass == USB_CLASS_RESERVE) { + if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) { + UefiDevicePathLibCatPrint ( + Str, + L"UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + return; + } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) { + UefiDevicePathLibCatPrint ( + Str, + L"UsbIrdaBridge(0x%x,0x%x,0x%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + return; + } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) { + UefiDevicePathLibCatPrint ( + Str, + L"UsbTestAndMeasurement(0x%x,0x%x,0x%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + return; + } + } + + UefiDevicePathLibCatPrint ( + Str, + L"UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceClass, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); +} + +/** + Converts a SATA device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextSata ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SATA_DEVICE_PATH *Sata; + + Sata = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"Sata(0x%x,0x%x,0x%x)", + Sata->HBAPortNumber, + Sata->PortMultiplierPortNumber, + Sata->Lun + ); +} + +/** + Converts a I20 device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + I2O_DEVICE_PATH *I2ODevPath; + + I2ODevPath = DevPath; + UefiDevicePathLibCatPrint (Str, L"I2O(0x%x)", I2ODevPath->Tid); +} + +/** + Converts a MAC address device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MAC_ADDR_DEVICE_PATH *MacDevPath; + UINTN HwAddressSize; + UINTN Index; + + MacDevPath = DevPath; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MacDevPath->IfType == 0x01 || MacDevPath->IfType == 0x00) { + HwAddressSize = 6; + } + + UefiDevicePathLibCatPrint (Str, L"MAC("); + + for (Index = 0; Index < HwAddressSize; Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", MacDevPath->MacAddress.Addr[Index]); + } + + UefiDevicePathLibCatPrint (Str, L",0x%x)", MacDevPath->IfType); +} + +/** + Converts network protocol string to its text representation. + + @param Str The string representative of input device. + @param Protocol The network protocol ID. + +**/ +VOID +CatNetworkProtocol ( + IN OUT POOL_PRINT *Str, + IN UINT16 Protocol + ) +{ + if (Protocol == RFC_1700_TCP_PROTOCOL) { + UefiDevicePathLibCatPrint (Str, L"TCP"); + } else if (Protocol == RFC_1700_UDP_PROTOCOL) { + UefiDevicePathLibCatPrint (Str, L"UDP"); + } else { + UefiDevicePathLibCatPrint (Str, L"0x%x", Protocol); + } +} + +/** + Converts IP v4 address to its text representation. + + @param Str The string representative of input device. + @param Address The IP v4 address. +**/ +VOID +CatIPv4Address ( + IN OUT POOL_PRINT *Str, + IN EFI_IPv4_ADDRESS *Address + ) +{ + UefiDevicePathLibCatPrint (Str, L"%d.%d.%d.%d", Address->Addr[0], Address->Addr[1], Address->Addr[2], Address->Addr[3]); +} + +/** + Converts IP v6 address to its text representation. + + @param Str The string representative of input device. + @param Address The IP v6 address. +**/ +VOID +CatIPv6Address ( + IN OUT POOL_PRINT *Str, + IN EFI_IPv6_ADDRESS *Address + ) +{ + UefiDevicePathLibCatPrint ( + Str, L"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + Address->Addr[0], Address->Addr[1], + Address->Addr[2], Address->Addr[3], + Address->Addr[4], Address->Addr[5], + Address->Addr[6], Address->Addr[7], + Address->Addr[8], Address->Addr[9], + Address->Addr[10], Address->Addr[11], + Address->Addr[12], Address->Addr[13], + Address->Addr[14], Address->Addr[15] + ); +} + +/** + Converts a IPv4 device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv4_DEVICE_PATH *IPDevPath; + + IPDevPath = DevPath; + UefiDevicePathLibCatPrint (Str, L"IPv4("); + CatIPv4Address (Str, &IPDevPath->RemoteIpAddress); + + if (DisplayOnly) { + UefiDevicePathLibCatPrint (Str, L")"); + return ; + } + + UefiDevicePathLibCatPrint (Str, L","); + CatNetworkProtocol (Str, IPDevPath->Protocol); + + UefiDevicePathLibCatPrint (Str, L",%s,", IPDevPath->StaticIpAddress ? L"Static" : L"DHCP"); + CatIPv4Address (Str, &IPDevPath->LocalIpAddress); + if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) { + UefiDevicePathLibCatPrint (Str, L","); + CatIPv4Address (Str, &IPDevPath->GatewayIpAddress); + UefiDevicePathLibCatPrint (Str, L","); + CatIPv4Address (Str, &IPDevPath->SubnetMask); + } + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts a IPv6 device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv6_DEVICE_PATH *IPDevPath; + + IPDevPath = DevPath; + UefiDevicePathLibCatPrint (Str, L"IPv6("); + CatIPv6Address (Str, &IPDevPath->RemoteIpAddress); + if (DisplayOnly) { + UefiDevicePathLibCatPrint (Str, L")"); + return ; + } + + UefiDevicePathLibCatPrint (Str, L","); + CatNetworkProtocol (Str, IPDevPath->Protocol); + + switch (IPDevPath->IpAddressOrigin) { + case 0: + UefiDevicePathLibCatPrint (Str, L",Static,"); + break; + case 1: + UefiDevicePathLibCatPrint (Str, L",StatelessAutoConfigure,"); + break; + default: + UefiDevicePathLibCatPrint (Str, L",StatefulAutoConfigure,"); + break; + } + + CatIPv6Address (Str, &IPDevPath->LocalIpAddress); + + if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) { + UefiDevicePathLibCatPrint (Str, L",0x%x,", IPDevPath->PrefixLength); + CatIPv6Address (Str, &IPDevPath->GatewayIpAddress); + } + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts an Infini Band device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)", + InfiniBand->ResourceFlags, + InfiniBand->PortGid, + InfiniBand->ServiceId, + InfiniBand->TargetPortId, + InfiniBand->DeviceId + ); +} + +/** + Converts a UART device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + + case 1: + Parity = 'N'; + break; + + case 2: + Parity = 'E'; + break; + + case 3: + Parity = 'O'; + break; + + case 4: + Parity = 'M'; + break; + + case 5: + Parity = 'S'; + break; + + default: + Parity = 'x'; + break; + } + + if (Uart->BaudRate == 0) { + UefiDevicePathLibCatPrint (Str, L"Uart(DEFAULT,"); + } else { + UefiDevicePathLibCatPrint (Str, L"Uart(%ld,", Uart->BaudRate); + } + + if (Uart->DataBits == 0) { + UefiDevicePathLibCatPrint (Str, L"DEFAULT,"); + } else { + UefiDevicePathLibCatPrint (Str, L"%d,", Uart->DataBits); + } + + UefiDevicePathLibCatPrint (Str, L"%c,", Parity); + + switch (Uart->StopBits) { + case 0: + UefiDevicePathLibCatPrint (Str, L"D)"); + break; + + case 1: + UefiDevicePathLibCatPrint (Str, L"1)"); + break; + + case 2: + UefiDevicePathLibCatPrint (Str, L"1.5)"); + break; + + case 3: + UefiDevicePathLibCatPrint (Str, L"2)"); + break; + + default: + UefiDevicePathLibCatPrint (Str, L"x)"); + break; + } +} + +/** + Converts an iSCSI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextiSCSI ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath; + UINT16 Options; + UINTN Index; + + ISCSIDevPath = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"iSCSI(%a,0x%x,0x", + ISCSIDevPath->TargetName, + ISCSIDevPath->TargetPortalGroupTag + ); + for (Index = 0; Index < sizeof (ISCSIDevPath->Lun) / sizeof (UINT8); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", ((UINT8 *)&ISCSIDevPath->Lun)[Index]); + } + Options = ISCSIDevPath->LoginOption; + UefiDevicePathLibCatPrint (Str, L",%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None"); + UefiDevicePathLibCatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None"); + if (((Options >> 11) & 0x0001) != 0) { + UefiDevicePathLibCatPrint (Str, L"%s,", L"None"); + } else if (((Options >> 12) & 0x0001) != 0) { + UefiDevicePathLibCatPrint (Str, L"%s,", L"CHAP_UNI"); + } else { + UefiDevicePathLibCatPrint (Str, L"%s,", L"CHAP_BI"); + + } + + UefiDevicePathLibCatPrint (Str, L"%s)", (ISCSIDevPath->NetworkProtocol == 0) ? L"TCP" : L"reserved"); +} + +/** + Converts a VLAN device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextVlan ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + VLAN_DEVICE_PATH *Vlan; + + Vlan = DevPath; + UefiDevicePathLibCatPrint (Str, L"Vlan(%d)", Vlan->VlanId); +} + +/** + Converts a Bluetooth device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextBluetooth ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BLUETOOTH_DEVICE_PATH *Bluetooth; + + Bluetooth = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"Bluetooth(%02x%02x%02x%02x%02x%02x)", + Bluetooth->BD_ADDR.Address[0], + Bluetooth->BD_ADDR.Address[1], + Bluetooth->BD_ADDR.Address[2], + Bluetooth->BD_ADDR.Address[3], + Bluetooth->BD_ADDR.Address[4], + Bluetooth->BD_ADDR.Address[5] + ); +} + +/** + Converts a Wi-Fi device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextWiFi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + WIFI_DEVICE_PATH *WiFi; + UINT8 SSId[33]; + + WiFi = DevPath; + + SSId[32] = '\0'; + CopyMem (SSId, WiFi->SSId, 32); + + UefiDevicePathLibCatPrint (Str, L"Wi-Fi(%a)", SSId); +} + +/** + Converts a Bluetooth device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextBluetoothLE ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BLUETOOTH_LE_DEVICE_PATH *BluetoothLE; + + BluetoothLE = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"BluetoothLE(%02x%02x%02x%02x%02x%02x,0x%02x)", + BluetoothLE->Address.Address[0], + BluetoothLE->Address.Address[1], + BluetoothLE->Address.Address[2], + BluetoothLE->Address.Address[3], + BluetoothLE->Address.Address[4], + BluetoothLE->Address.Address[5], + BluetoothLE->Address.Type + ); +} + +/** + Converts a DNS device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextDns ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + DNS_DEVICE_PATH *DnsDevPath; + UINT32 DnsServerIpCount; + UINT32 DnsServerIpIndex; + + DnsDevPath = DevPath; + DnsServerIpCount = (UINT32) (DevicePathNodeLength(DnsDevPath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof (DnsDevPath->IsIPv6)) / sizeof (EFI_IP_ADDRESS); + + UefiDevicePathLibCatPrint (Str, L"Dns("); + + for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) { + if (DnsDevPath->IsIPv6 == 0x00) { + CatIPv4Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v4)); + } else { + CatIPv6Address (Str, &(DnsDevPath->DnsServerIp[DnsServerIpIndex].v6)); + } + + if (DnsServerIpIndex < DnsServerIpCount - 1) { + UefiDevicePathLibCatPrint (Str, L","); + } + } + + UefiDevicePathLibCatPrint (Str, L")"); +} + +/** + Converts a URI device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextUri ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + URI_DEVICE_PATH *Uri; + UINTN UriLength; + CHAR8 *UriStr; + + // + // Uri in the device path may not be null terminated. + // + Uri = DevPath; + UriLength = DevicePathNodeLength (Uri) - sizeof (URI_DEVICE_PATH); + UriStr = AllocatePool (UriLength + 1); + ASSERT (UriStr != NULL); + + CopyMem (UriStr, Uri->Uri, UriLength); + UriStr[UriLength] = '\0'; + UefiDevicePathLibCatPrint (Str, L"Uri(%a)", UriStr); + FreePool (UriStr); +} + +/** + Converts a Hard drive device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case SIGNATURE_TYPE_MBR: + UefiDevicePathLibCatPrint ( + Str, + L"HD(%d,%s,0x%08x,", + Hd->PartitionNumber, + L"MBR", + *((UINT32 *) (&(Hd->Signature[0]))) + ); + break; + + case SIGNATURE_TYPE_GUID: + UefiDevicePathLibCatPrint ( + Str, + L"HD(%d,%s,%g,", + Hd->PartitionNumber, + L"GPT", + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + + default: + UefiDevicePathLibCatPrint ( + Str, + L"HD(%d,%d,0,", + Hd->PartitionNumber, + Hd->SignatureType + ); + break; + } + + UefiDevicePathLibCatPrint (Str, L"0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize); +} + +/** + Converts a CDROM device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + if (DisplayOnly) { + UefiDevicePathLibCatPrint (Str, L"CDROM(0x%x)", Cd->BootEntry); + return ; + } + + UefiDevicePathLibCatPrint (Str, L"CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize); +} + +/** + Converts a File device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + UefiDevicePathLibCatPrint (Str, L"%s", Fp->PathName); +} + +/** + Converts a Media protocol device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + UefiDevicePathLibCatPrint (Str, L"Media(%g)", &MediaProt->Protocol); +} + +/** + Converts a Firmware Volume device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextFv ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_FW_VOL_DEVICE_PATH *Fv; + + Fv = DevPath; + UefiDevicePathLibCatPrint (Str, L"Fv(%g)", &Fv->FvName); +} + +/** + Converts a Firmware Volume File device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextFvFile ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile; + + FvFile = DevPath; + UefiDevicePathLibCatPrint (Str, L"FvFile(%g)", &FvFile->FvFileName); +} + +/** + Converts a Relative Offset device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathRelativeOffsetRange ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + Offset = DevPath; + UefiDevicePathLibCatPrint ( + Str, + L"Offset(0x%lx,0x%lx)", + Offset->StartingOffset, + Offset->EndingOffset + ); +} + +/** + Converts a Ram Disk device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextRamDisk ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + + RamDisk = DevPath; + + if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid)) { + UefiDevicePathLibCatPrint ( + Str, + L"VirtualDisk(0x%lx,0x%lx,%d)", + LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0], + LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0], + RamDisk->Instance + ); + } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid)) { + UefiDevicePathLibCatPrint ( + Str, + L"VirtualCD(0x%lx,0x%lx,%d)", + LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0], + LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0], + RamDisk->Instance + ); + } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid)) { + UefiDevicePathLibCatPrint ( + Str, + L"PersistentVirtualDisk(0x%lx,0x%lx,%d)", + LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0], + LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0], + RamDisk->Instance + ); + } else if (CompareGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid)) { + UefiDevicePathLibCatPrint ( + Str, + L"PersistentVirtualCD(0x%lx,0x%lx,%d)", + LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0], + LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0], + RamDisk->Instance + ); + } else { + UefiDevicePathLibCatPrint ( + Str, + L"RamDisk(0x%lx,0x%lx,%d,%g)", + LShiftU64 ((UINT64)RamDisk->StartingAddr[1], 32) | RamDisk->StartingAddr[0], + LShiftU64 ((UINT64)RamDisk->EndingAddr[1], 32) | RamDisk->EndingAddr[0], + RamDisk->Instance, + &RamDisk->TypeGuid + ); + } +} + +/** + Converts a BIOS Boot Specification device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextBBS ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BBS_BBS_DEVICE_PATH *Bbs; + CHAR16 *Type; + + Bbs = DevPath; + switch (Bbs->DeviceType) { + case BBS_TYPE_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_TYPE_HARDDRIVE: + Type = L"HD"; + break; + + case BBS_TYPE_CDROM: + Type = L"CDROM"; + break; + + case BBS_TYPE_PCMCIA: + Type = L"PCMCIA"; + break; + + case BBS_TYPE_USB: + Type = L"USB"; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + Type = L"Network"; + break; + + default: + Type = NULL; + break; + } + + if (Type != NULL) { + UefiDevicePathLibCatPrint (Str, L"BBS(%s,%a", Type, Bbs->String); + } else { + UefiDevicePathLibCatPrint (Str, L"BBS(0x%x,%a", Bbs->DeviceType, Bbs->String); + } + + if (DisplayOnly) { + UefiDevicePathLibCatPrint (Str, L")"); + return ; + } + + UefiDevicePathLibCatPrint (Str, L",0x%x)", Bbs->StatusFlag); +} + +/** + Converts an End-of-Device-Path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + UefiDevicePathLibCatPrint (Str, L","); +} + +GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_GENERIC_TABLE mUefiDevicePathLibToTextTableGeneric[] = { + {HARDWARE_DEVICE_PATH, L"HardwarePath" }, + {ACPI_DEVICE_PATH, L"AcpiPath" }, + {MESSAGING_DEVICE_PATH, L"Msg" }, + {MEDIA_DEVICE_PATH, L"MediaPath" }, + {BBS_DEVICE_PATH, L"BbsPath" }, + {0, NULL} +}; + +/** + Converts an unknown device path structure to its string representative. + + @param Str The string representative of input device. + @param DevPath The input device path structure. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + +**/ +VOID +DevPathToTextNodeGeneric ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + UINTN Index; + + Node = DevPath; + + for (Index = 0; mUefiDevicePathLibToTextTableGeneric[Index].Text != NULL; Index++) { + if (DevicePathType (Node) == mUefiDevicePathLibToTextTableGeneric[Index].Type) { + break; + } + } + + if (mUefiDevicePathLibToTextTableGeneric[Index].Text == NULL) { + // + // It's a node whose type cannot be recognized + // + UefiDevicePathLibCatPrint (Str, L"Path(%d,%d", DevicePathType (Node), DevicePathSubType (Node)); + } else { + // + // It's a node whose type can be recognized + // + UefiDevicePathLibCatPrint (Str, L"%s(%d", mUefiDevicePathLibToTextTableGeneric[Index].Text, DevicePathSubType (Node)); + } + + Index = sizeof (EFI_DEVICE_PATH_PROTOCOL); + if (Index < DevicePathNodeLength (Node)) { + UefiDevicePathLibCatPrint (Str, L","); + for (; Index < DevicePathNodeLength (Node); Index++) { + UefiDevicePathLibCatPrint (Str, L"%02x", ((UINT8 *) Node)[Index]); + } + } + + UefiDevicePathLibCatPrint (Str, L")"); +} + +GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_TABLE mUefiDevicePathLibToTextTable[] = { + {HARDWARE_DEVICE_PATH, HW_PCI_DP, DevPathToTextPci }, + {HARDWARE_DEVICE_PATH, HW_PCCARD_DP, DevPathToTextPccard }, + {HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, DevPathToTextMemMap }, + {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DevPathToTextVendor }, + {HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, DevPathToTextController }, + {HARDWARE_DEVICE_PATH, HW_BMC_DP, DevPathToTextBmc }, + {ACPI_DEVICE_PATH, ACPI_DP, DevPathToTextAcpi }, + {ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, DevPathToTextAcpiEx }, + {ACPI_DEVICE_PATH, ACPI_ADR_DP, DevPathToTextAcpiAdr }, + {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, DevPathToTextAtapi }, + {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, DevPathToTextScsi }, + {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, DevPathToTextFibre }, + {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP, DevPathToTextFibreEx }, + {MESSAGING_DEVICE_PATH, MSG_SASEX_DP, DevPathToTextSasEx }, + {MESSAGING_DEVICE_PATH, MSG_NVME_NAMESPACE_DP, DevPathToTextNVMe }, + {MESSAGING_DEVICE_PATH, MSG_UFS_DP, DevPathToTextUfs }, + {MESSAGING_DEVICE_PATH, MSG_SD_DP, DevPathToTextSd }, + {MESSAGING_DEVICE_PATH, MSG_EMMC_DP, DevPathToTextEmmc }, + {MESSAGING_DEVICE_PATH, MSG_1394_DP, DevPathToText1394 }, + {MESSAGING_DEVICE_PATH, MSG_USB_DP, DevPathToTextUsb }, + {MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP, DevPathToTextUsbWWID }, + {MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP, DevPathToTextLogicalUnit }, + {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, DevPathToTextUsbClass }, + {MESSAGING_DEVICE_PATH, MSG_SATA_DP, DevPathToTextSata }, + {MESSAGING_DEVICE_PATH, MSG_I2O_DP, DevPathToTextI2O }, + {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, DevPathToTextMacAddr }, + {MESSAGING_DEVICE_PATH, MSG_IPv4_DP, DevPathToTextIPv4 }, + {MESSAGING_DEVICE_PATH, MSG_IPv6_DP, DevPathToTextIPv6 }, + {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, DevPathToTextInfiniBand }, + {MESSAGING_DEVICE_PATH, MSG_UART_DP, DevPathToTextUart }, + {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, DevPathToTextVendor }, + {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP, DevPathToTextiSCSI }, + {MESSAGING_DEVICE_PATH, MSG_VLAN_DP, DevPathToTextVlan }, + {MESSAGING_DEVICE_PATH, MSG_DNS_DP, DevPathToTextDns }, + {MESSAGING_DEVICE_PATH, MSG_URI_DP, DevPathToTextUri }, + {MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_DP, DevPathToTextBluetooth }, + {MESSAGING_DEVICE_PATH, MSG_WIFI_DP, DevPathToTextWiFi }, + {MESSAGING_DEVICE_PATH, MSG_BLUETOOTH_LE_DP, DevPathToTextBluetoothLE }, + {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, DevPathToTextHardDrive }, + {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, DevPathToTextCDROM }, + {MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, DevPathToTextVendor }, + {MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, DevPathToTextMediaProtocol }, + {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath }, + {MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_VOL_DP, DevPathToTextFv }, + {MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP, DevPathToTextFvFile }, + {MEDIA_DEVICE_PATH, MEDIA_RELATIVE_OFFSET_RANGE_DP, DevPathRelativeOffsetRange }, + {MEDIA_DEVICE_PATH, MEDIA_RAM_DISK_DP, DevPathToTextRamDisk }, + {BBS_DEVICE_PATH, BBS_BBS_DP, DevPathToTextBBS }, + {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance }, + {0, 0, NULL} +}; + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + POOL_PRINT Str; + UINTN Index; + DEVICE_PATH_TO_TEXT ToText; + + if (DeviceNode == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Process the device path node + // If not found, use a generic function + // + ToText = DevPathToTextNodeGeneric; + for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index++) { + if (DevicePathType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].Type && + DevicePathSubType (DeviceNode) == mUefiDevicePathLibToTextTable[Index].SubType + ) { + ToText = mUefiDevicePathLibToTextTable[Index].Function; + break; + } + } + + // + // Print this node + // + ToText (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts); + + ASSERT (Str.Str != NULL); + return Str.Str; +} + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + POOL_PRINT Str; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *AlignedNode; + UINTN Index; + DEVICE_PATH_TO_TEXT ToText; + + if (DevicePath == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Process each device path node + // + Node = (EFI_DEVICE_PATH_PROTOCOL *) DevicePath; + while (!IsDevicePathEnd (Node)) { + // + // Find the handler to dump this device path node + // If not found, use a generic function + // + ToText = DevPathToTextNodeGeneric; + for (Index = 0; mUefiDevicePathLibToTextTable[Index].Function != NULL; Index += 1) { + + if (DevicePathType (Node) == mUefiDevicePathLibToTextTable[Index].Type && + DevicePathSubType (Node) == mUefiDevicePathLibToTextTable[Index].SubType + ) { + ToText = mUefiDevicePathLibToTextTable[Index].Function; + break; + } + } + // + // Put a path separator in if needed + // + if ((Str.Count != 0) && (ToText != DevPathToTextEndInstance)) { + if (Str.Str[Str.Count] != L',') { + UefiDevicePathLibCatPrint (&Str, L"/"); + } + } + + AlignedNode = AllocateCopyPool (DevicePathNodeLength (Node), Node); + // + // Print this node of the device path + // + ToText (&Str, AlignedNode, DisplayOnly, AllowShortcuts); + FreePool (AlignedNode); + + // + // Next device path node + // + Node = NextDevicePathNode (Node); + } + + if (Str.Str == NULL) { + return AllocateZeroPool (sizeof (CHAR16)); + } else { + return Str.Str; + } +} diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c new file mode 100644 index 000000000..9274ef8dd --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c @@ -0,0 +1,897 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +// +// Template for an end-of-device path node. +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } +}; + +/** + Determine whether a given device path is valid. + + @param DevicePath A pointer to a device path data structure. + @param MaxSize The maximum size of the device path data structure. + + @retval TRUE DevicePath is valid. + @retval FALSE DevicePath is NULL. + @retval FALSE Maxsize is less than sizeof(EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE The length of any node node in the DevicePath is less + than sizeof (EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE If MaxSize is not zero, the size of the DevicePath + exceeds MaxSize. + @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node + count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. +**/ +BOOLEAN +EFIAPI +IsDevicePathValid ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN MaxSize + ) +{ + UINTN Count; + UINTN Size; + UINTN NodeLength; + + // + //Validate the input whether exists and its size big enough to touch the first node + // + if (DevicePath == NULL || (MaxSize > 0 && MaxSize < END_DEVICE_PATH_LENGTH)) { + return FALSE; + } + + if (MaxSize == 0) { + MaxSize = MAX_UINTN; + } + + for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + NodeLength = DevicePathNodeLength (DevicePath); + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + if (NodeLength > MAX_UINTN - Size) { + return FALSE; + } + Size += NodeLength; + + // + // Validate next node before touch it. + // + if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { + return FALSE; + } + + if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) { + Count++; + if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) { + return FALSE; + } + } + + // + // FilePath must be a NULL-terminated string. + // + if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH && + DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP && + *(CHAR16 *)((UINT8 *)DevicePath + NodeLength - 2) != 0) { + return FALSE; + } + } + + // + // Only return TRUE when the End Device Path node is valid. + // + return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); +} + + +/** + Returns the Type field of a device path node. + + Returns the Type field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The Type field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type; +} + +/** + Returns the SubType field of a device path node. + + Returns the SubType field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The SubType field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathSubType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType; +} + +/** + Returns the 16-bit Length field of a device path node. + + Returns the 16-bit Length field of the device path node specified by Node. + Node is not required to be aligned on a 16-bit boundary, so it is recommended + that a function such as ReadUnaligned16() be used to extract the contents of + the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The 16-bit Length field of the device path node specified by Node. + +**/ +UINTN +EFIAPI +DevicePathNodeLength ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]); +} + +/** + Returns a pointer to the next node in a device path. + + Returns a pointer to the device path node that follows the device path node + specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +NextDevicePathNode ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node)); +} + +/** + Determines if a device path node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that + are the end of an entire device path. + + Determines if the device path node specified by Node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that are the + end of an entire device path. If Node represents an end node of a device path, + then TRUE is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is an end node of a + device path. + @retval FALSE The device path node specified by Node is not an end node of + a device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE); +} + +/** + Determines if a device path node is an end node of an entire device path. + + Determines if a device path node specified by Node is an end node of an entire + device path. If Node represents the end of an entire device path, then TRUE is + returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of an entire + device path. + @retval FALSE The device path node specified by Node is not the end of an + entire device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEnd ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE); +} + +/** + Determines if a device path node is an end node of a device path instance. + + Determines if a device path node specified by Node is an end node of a device + path instance. If Node represents the end of a device path instance, then TRUE + is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of a device + path instance. + @retval FALSE The device path node specified by Node is not the end of a + device path instance. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndInstance ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE); +} + +/** + Sets the length, in bytes, of a device path node. + + Sets the length of the device path node specified by Node to the value specified + by NodeLength. NodeLength is returned. Node is not required to be aligned on + a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16() + be used to set the contents of the Length field. + + If Node is NULL, then ASSERT(). + If NodeLength >= SIZE_64KB, then ASSERT(). + If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT(). + + @param Node A pointer to a device path node data structure. + @param Length The length, in bytes, of the device path node. + + @return Length + +**/ +UINT16 +EFIAPI +SetDevicePathNodeLength ( + IN OUT VOID *Node, + IN UINTN Length + ) +{ + ASSERT (Node != NULL); + ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB)); + return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length)); +} + +/** + Fills in all the fields of a device path node that is the end of an entire device path. + + Fills in all the fields of a device path node specified by Node so Node represents + the end of an entire device path. The Type field of Node is set to + END_DEVICE_PATH_TYPE, the SubType field of Node is set to + END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to + END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary, + so it is recommended that a function such as WriteUnaligned16() be used to set + the contents of the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + +**/ +VOID +EFIAPI +SetDevicePathEndNode ( + OUT VOID *Node + ) +{ + ASSERT (Node != NULL); + CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath)); +} + +/** + 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 or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +UefiDevicePathLibGetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibDuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN Size; + + // + // Compute the size + // + Size = GetDevicePathSize (DevicePath); + if (Size == 0) { + return NULL; + } + + // + // Allocate space for duplicate device path + // + + return AllocateCopyPool (Size, DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath2; + + // + // If there's only 1 path, just duplicate it. + // + if (FirstDevicePath == NULL) { + return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath); + } + + if (SecondDevicePath == NULL) { + return DuplicateDevicePath (FirstDevicePath); + } + + if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) { + return NULL; + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL. + // + Size1 = GetDevicePathSize (FirstDevicePath); + Size2 = GetDevicePathSize (SecondDevicePath); + Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH; + + NewDevicePath = AllocatePool (Size); + + if (NewDevicePath != NULL) { + NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1); + // + // Over write FirstDevicePath EndNode and do the copy + // + DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + + (Size1 - END_DEVICE_PATH_LENGTH)); + CopyMem (DevicePath2, SecondDevicePath, Size2); + } + + return NewDevicePath; +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN NodeLength; + + if (DevicePathNode == NULL) { + return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath); + } + // + // Build a Node that has a terminator on it + // + NodeLength = DevicePathNodeLength (DevicePathNode); + + TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH); + if (TempDevicePath == NULL) { + return NULL; + } + TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength); + // + // Add and end device path node to convert Node to device path + // + NextNode = NextDevicePathNode (TempDevicePath); + SetDevicePathEndNode (NextNode); + // + // Append device paths + // + NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath); + + FreePool (TempDevicePath); + + return NewDevicePath; +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINTN SrcSize; + UINTN InstanceSize; + + if (DevicePath == NULL) { + return DuplicateDevicePath (DevicePathInstance); + } + + if (DevicePathInstance == NULL) { + return NULL; + } + + if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) { + return NULL; + } + + SrcSize = GetDevicePathSize (DevicePath); + InstanceSize = GetDevicePathSize (DevicePathInstance); + + NewDevicePath = AllocatePool (SrcSize + InstanceSize); + if (NewDevicePath != NULL) { + + TempDevicePath = CopyMem (NewDevicePath, DevicePath, SrcSize);; + + while (!IsDevicePathEnd (TempDevicePath)) { + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + TempDevicePath = NextDevicePathNode (TempDevicePath); + CopyMem (TempDevicePath, DevicePathInstance, InstanceSize); + } + + return NewDevicePath; +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibGetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *ReturnValue; + UINT8 Temp; + + ASSERT (Size != NULL); + + if (DevicePath == NULL || *DevicePath == NULL) { + *Size = 0; + return NULL; + } + + if (!IsDevicePathValid (*DevicePath, 0)) { + return NULL; + } + + // + // Find the end of the device path instance + // + DevPath = *DevicePath; + while (!IsDevicePathEndType (DevPath)) { + DevPath = NextDevicePathNode (DevPath); + } + + // + // Compute the size of the device path instance + // + *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Make a copy and return the device path instance + // + Temp = DevPath->SubType; + DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + ReturnValue = DuplicateDevicePath (*DevicePath); + DevPath->SubType = Temp; + + // + // If DevPath is the end of an entire device path, then another instance + // does not follow, so *DevicePath is set to NULL. + // + if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *DevicePath = NULL; + } else { + *DevicePath = NextDevicePathNode (DevPath); + } + + return ReturnValue; +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibCreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + // + // NodeLength is less than the size of the header. + // + return NULL; + } + + DevicePath = AllocateZeroPool (NodeLength); + if (DevicePath != NULL) { + DevicePath->Type = NodeType; + DevicePath->SubType = NodeSubType; + SetDevicePathNodeLength (DevicePath, NodeLength); + } + + return DevicePath; +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +UefiDevicePathLibIsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return FALSE; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + if (IsDevicePathEndInstance (Node)) { + return TRUE; + } + + Node = NextDevicePathNode (Node); + } + + return FALSE; +} + + +/** + Retrieves the device path protocol from a handle. + + This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL + is returned. + + @param Handle The handle from which to retrieve the device + path protocol. + + @return The device path protocol from the handle specified by Handle. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} + +/** + Allocates a device path for a file and appends it to an existing device path. + + If Device is a valid device handle that contains a device path protocol, then a device path for + the file specified by FileName is allocated and appended to the device path associated with the + handle Device. The allocated device path is returned. If Device is NULL or Device is a handle + that does not support the device path protocol, then a device path containing a single device + path node for the file specified by FileName is allocated and returned. + The memory for the new device path is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + If FileName is NULL, then ASSERT(). + If FileName is not aligned on a 16-bit boundary, then ASSERT(). + + @param Device A pointer to a device handle. This parameter + is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return The allocated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + + DevicePath = NULL; + + Size = StrSize (FileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, FileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + if (Device != NULL) { + DevicePath = DevicePathFromHandle (Device); + } + + DevicePath = AppendDevicePath (DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + return DevicePath; +} + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c new file mode 100644 index 000000000..aac768616 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c @@ -0,0 +1,354 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiDevicePathLib.h" + +/** + 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 or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibGetDevicePathSize (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibDuplicateDevicePath (DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath); +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode); +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance); +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size); +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength); +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath); +} + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + return UefiDevicePathLibConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts); +} + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + return UefiDevicePathLibConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts); +} + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +{ + return UefiDevicePathLibConvertTextToDeviceNode (TextDeviceNode); +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +{ + return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath); +} diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h new file mode 100644 index 000000000..8e9b8f8f4 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h @@ -0,0 +1,451 @@ +/** @file + Definition for Device Path library. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _UEFI_DEVICE_PATH_LIB_H_ +#define _UEFI_DEVICE_PATH_LIB_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_COMMA(a) ((a) == L',') +#define IS_HYPHEN(a) ((a) == L'-') +#define IS_DOT(a) ((a) == L'.') +#define IS_LEFT_PARENTH(a) ((a) == L'(') +#define IS_RIGHT_PARENTH(a) ((a) == L')') +#define IS_SLASH(a) ((a) == L'/') +#define IS_NULL(a) ((a) == L'\0') + + +// +// Private Data structure +// +typedef struct { + CHAR16 *Str; + UINTN Count; + UINTN Capacity; +} POOL_PRINT; + +typedef +EFI_DEVICE_PATH_PROTOCOL * +(*DEVICE_PATH_FROM_TEXT) ( + IN CHAR16 *Str + ); + +typedef +VOID +(*DEVICE_PATH_TO_TEXT) ( + IN OUT POOL_PRINT *Str, + IN VOID *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef struct { + UINT8 Type; + UINT8 SubType; + DEVICE_PATH_TO_TEXT Function; +} DEVICE_PATH_TO_TEXT_TABLE; + +typedef struct { + UINT8 Type; + CHAR16 *Text; +} DEVICE_PATH_TO_TEXT_GENERIC_TABLE; + +typedef struct { + CHAR16 *DevicePathNodeText; + DEVICE_PATH_FROM_TEXT Function; +} DEVICE_PATH_FROM_TEXT_TABLE; + +typedef struct { + BOOLEAN ClassExist; + UINT8 Class; + BOOLEAN SubClassExist; + UINT8 SubClass; +} USB_CLASS_TEXT; + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_CDCCONTROL 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDCDATA 10 +#define USB_CLASS_SMART_CARD 11 +#define USB_CLASS_VIDEO 14 +#define USB_CLASS_DIAGNOSTIC 220 +#define USB_CLASS_WIRELESS 224 + +#define USB_CLASS_RESERVE 254 +#define USB_SUBCLASS_FW_UPDATE 1 +#define USB_SUBCLASS_IRDA_BRIDGE 2 +#define USB_SUBCLASS_TEST 3 + +#define RFC_1700_UDP_PROTOCOL 17 +#define RFC_1700_TCP_PROTOCOL 6 + +#pragma pack(1) + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_HARDWARE_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MESSAGING_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MEDIA_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Hid; + UINT32 Uid; + UINT32 Cid; + CHAR8 HidUidCidStr[3]; +} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + CHAR8 TargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +#pragma pack() + +/** + 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 or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +UefiDevicePathLibGetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibDuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ); + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ); + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ); + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibGetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ); + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibCreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ); + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +UefiDevicePathLibIsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ); + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf new file mode 100644 index 000000000..3c41c0695 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf @@ -0,0 +1,74 @@ +## @file +# Instance of Device Path Library based on Memory Allocation Library. +# +# Device Path Library that layers on top of the Memory Allocation Library. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDevicePathLib + MODULE_UNI_FILE = UefiDevicePathLib.uni + FILE_GUID = 91c1677a-e57f-4191-8b8e-eb7711a716e0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DevicePathLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE MM_STANDALONE + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DevicePathUtilities.c + DevicePathToText.c + DevicePathFromText.c + UefiDevicePathLib.c + UefiDevicePathLib.h + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + MemoryAllocationLib + DebugLib + BaseMemoryLib + PcdLib + PrintLib + +[Guids] + ## SOMETIMES_CONSUMES ## GUID + gEfiVTUTF8Guid + ## SOMETIMES_CONSUMES ## GUID + gEfiVT100Guid + ## SOMETIMES_CONSUMES ## GUID + gEfiVT100PlusGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPcAnsiGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiUartDevicePathGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiSasDevicePathGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiVirtualDiskGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiVirtualCdGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPersistentVirtualDiskGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPersistentVirtualCdGuid + +[Protocols] + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiDebugPortProtocolGuid ## UNDEFINED + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount ## SOMETIMES_CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni new file mode 100644 index 000000000..34cd8427c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Instance of Device Path Library based on Memory Allocation Library. +// +// Device Path Library that layers on top of the Memory Allocation Library. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Device Path Library based on Memory Allocation Library" + +#string STR_MODULE_DESCRIPTION #language en-US "This Device Path Library layers on top of the Memory Allocation Library." + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c new file mode 100644 index 000000000..106ff245c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c @@ -0,0 +1,478 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiDevicePathLib.h" + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathLibDevicePathUtilities = NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathLibDevicePathToText = NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mDevicePathLibDevicePathFromText = NULL; + +/** + The constructor function caches the pointer to DevicePathUtilites protocol, + DevicePathToText protocol and DevicePathFromText protocol. + + The constructor function locates these three protocols from protocol database. + It will caches the pointer to local protocol instance 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +UefiDevicePathLibOptionalDevicePathProtocolConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDevicePathUtilitiesProtocolGuid, + NULL, + (VOID**) &mDevicePathLibDevicePathUtilities + ); + ASSERT_EFI_ERROR (Status); + ASSERT (mDevicePathLibDevicePathUtilities != NULL); + 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 or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->GetDevicePathSize (DevicePath); + } else { + return UefiDevicePathLibGetDevicePathSize (DevicePath); + } +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->DuplicateDevicePath (DevicePath); + } else { + return UefiDevicePathLibDuplicateDevicePath (DevicePath); + } +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath); + } else { + return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath); + } +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode); + } else { + return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode); + } +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance); + } else { + return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance); + } +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size); + } else { + return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size); + } +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength); + } else { + return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength); + } +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (mDevicePathLibDevicePathUtilities != NULL) { + return mDevicePathLibDevicePathUtilities->IsDevicePathMultiInstance (DevicePath); + } else { + return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath); + } +} + +/** + Locate and return the protocol instance identified by the ProtocolGuid. + + @param ProtocolGuid The GUID of the protocol. + + @return A pointer to the protocol instance or NULL when absent. +**/ +VOID * +UefiDevicePathLibLocateProtocol ( + EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + VOID *Protocol; + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + (VOID**) &Protocol + ); + if (EFI_ERROR (Status)) { + return NULL; + } else { + return Protocol; + } +} + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + if (mDevicePathLibDevicePathToText == NULL) { + mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid); + } + if (mDevicePathLibDevicePathToText != NULL) { + return mDevicePathLibDevicePathToText->ConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts); + } + + return UefiDevicePathLibConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts); +} + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + if (mDevicePathLibDevicePathToText == NULL) { + mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid); + } + if (mDevicePathLibDevicePathToText != NULL) { + return mDevicePathLibDevicePathToText->ConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts); + } + + return UefiDevicePathLibConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts); +} + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +{ + if (mDevicePathLibDevicePathFromText == NULL) { + mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid); + } + if (mDevicePathLibDevicePathFromText != NULL) { + return mDevicePathLibDevicePathFromText->ConvertTextToDeviceNode (TextDeviceNode); + } + + return UefiDevicePathLibConvertTextToDeviceNode (TextDeviceNode); +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +{ + if (mDevicePathLibDevicePathFromText == NULL) { + mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid); + } + if (mDevicePathLibDevicePathFromText != NULL) { + return mDevicePathLibDevicePathFromText->ConvertTextToDevicePath (TextDevicePath); + } + + return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath); +} + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf new file mode 100644 index 000000000..e812e3e1d --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf @@ -0,0 +1,84 @@ +## @file +# Instance of Device Path Library based on Device Path Protocol. +# +# Device Path Library that layers on top of the UEFI 2.0 Device Path Protocol. +# If the DevicePathFromText/DevicePathToText protocol doesn't exist, the library +# uses its internal conversion logic. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDevicePathLibOptionalDevicePathProtocol + MODULE_UNI_FILE = UefiDevicePathLibOptionalDevicePathProtocol.uni + FILE_GUID = 3E1C696D-FCF0-45a7-85A7-E86C2A1C1080 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DevicePathLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = UefiDevicePathLibOptionalDevicePathProtocolConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DevicePathUtilities.c + DevicePathToText.c + DevicePathFromText.c + UefiDevicePathLibOptionalDevicePathProtocol.c + UefiDevicePathLib.h + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + MemoryAllocationLib + DebugLib + BaseMemoryLib + PcdLib + PrintLib + +[Guids] + ## SOMETIMES_CONSUMES ## GUID + gEfiVTUTF8Guid + ## SOMETIMES_CONSUMES ## GUID + gEfiVT100Guid + ## SOMETIMES_CONSUMES ## GUID + gEfiVT100PlusGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPcAnsiGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiUartDevicePathGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiSasDevicePathGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiVirtualDiskGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiVirtualCdGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPersistentVirtualDiskGuid + ## SOMETIMES_CONSUMES ## GUID + gEfiPersistentVirtualCdGuid + +[Protocols] + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathUtilitiesProtocolGuid ## CONSUMES + gEfiDevicePathToTextProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES + gEfiDebugPortProtocolGuid ## UNDEFINED + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount ## SOMETIMES_CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiDevicePathUtilitiesProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni new file mode 100644 index 000000000..070f0add9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni @@ -0,0 +1,18 @@ +// /** @file +// Instance of Device Path Library based on Device Path Protocol. +// +// Device Path Library that layers on top of the UEFI 2.0 Device Path Protocol. +// If the DevicePathFromText/DevicePathToText protocol doesn't exist, the library +// uses its internal conversion logic. +// +// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Device Path Library based on Device Path Protocol." + +#string STR_MODULE_DESCRIPTION #language en-US "Instance of Device Path Library based on Device Path Protocol." + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c new file mode 100644 index 000000000..5a8f293f9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c @@ -0,0 +1,865 @@ +/** @file + Library instance that implement UEFI Device Path Library class based on protocol + gEfiDevicePathUtilitiesProtocolGuid. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathLibDevicePathUtilities = NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathLibDevicePathToText = NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mDevicePathLibDevicePathFromText = NULL; + +// +// Template for an end-of-device path node. +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } +}; + +/** + The constructor function caches the pointer to DevicePathUtilites protocol. + + The constructor function locates DevicePathUtilities protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DevicePathLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDevicePathUtilitiesProtocolGuid, + NULL, + (VOID**) &mDevicePathLibDevicePathUtilities + ); + ASSERT_EFI_ERROR (Status); + ASSERT (mDevicePathLibDevicePathUtilities != NULL); + return Status; +} + +/** + Determine whether a given device path is valid. + If DevicePath is NULL, then ASSERT(). + + @param DevicePath A pointer to a device path data structure. + @param MaxSize The maximum size of the device path data structure. + + @retval TRUE DevicePath is valid. + @retval FALSE The length of any node node in the DevicePath is less + than sizeof (EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE If MaxSize is not zero, the size of the DevicePath + exceeds MaxSize. + @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node + count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. +**/ +BOOLEAN +EFIAPI +IsDevicePathValid ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN MaxSize + ) +{ + UINTN Count; + UINTN Size; + UINTN NodeLength; + + ASSERT (DevicePath != NULL); + + if (MaxSize == 0) { + MaxSize = MAX_UINTN; + } + + // + // Validate the input size big enough to touch the first node. + // + if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + NodeLength = DevicePathNodeLength (DevicePath); + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + if (NodeLength > MAX_UINTN - Size) { + return FALSE; + } + Size += NodeLength; + + // + // Validate next node before touch it. + // + if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { + return FALSE; + } + + if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) { + Count++; + if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) { + return FALSE; + } + } + + // + // FilePath must be a NULL-terminated string. + // + if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH && + DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP && + *(CHAR16 *)((UINT8 *)DevicePath + NodeLength - 2) != 0) { + return FALSE; + } + } + + // + // Only return TRUE when the End Device Path node is valid. + // + return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); +} + +/** + Returns the Type field of a device path node. + + Returns the Type field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The Type field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type; +} + +/** + Returns the SubType field of a device path node. + + Returns the SubType field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The SubType field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathSubType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType; +} + +/** + Returns the 16-bit Length field of a device path node. + + Returns the 16-bit Length field of the device path node specified by Node. + Node is not required to be aligned on a 16-bit boundary, so it is recommended + that a function such as ReadUnaligned16() be used to extract the contents of + the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The 16-bit Length field of the device path node specified by Node. + +**/ +UINTN +EFIAPI +DevicePathNodeLength ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]); +} + +/** + Returns a pointer to the next node in a device path. + + Returns a pointer to the device path node that follows the device path node + specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +NextDevicePathNode ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node)); +} + +/** + Determines if a device path node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that + are the end of an entire device path. + + Determines if the device path node specified by Node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that are the + end of an entire device path. If Node represents an end node of a device path, + then TRUE is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is an end node of a device path. + @retval FALSE The device path node specified by Node is not an end node of + a device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE); +} + +/** + Determines if a device path node is an end node of an entire device path. + + Determines if a device path node specified by Node is an end node of an entire + device path. + If Node represents the end of an entire device path, then TRUE is returned. + Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of an entire device path. + @retval FALSE The device path node specified by Node is not the end of an entire device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEnd ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE); +} + +/** + Determines if a device path node is an end node of a device path instance. + + Determines if a device path node specified by Node is an end node of a device + path instance. + If Node represents the end of a device path instance, then TRUE is returned. + Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of a device + path instance. + @retval FALSE The device path node specified by Node is not the end of a + device path instance. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndInstance ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE); +} + +/** + Sets the length, in bytes, of a device path node. + + Sets the length of the device path node specified by Node to the value specified + by NodeLength. NodeLength is returned. Node is not required to be aligned on + a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16() + be used to set the contents of the Length field. + + If Node is NULL, then ASSERT(). + If NodeLength >= SIZE_64KB, then ASSERT(). + If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT(). + + @param Node A pointer to a device path node data structure. + @param Length The length, in bytes, of the device path node. + + @return Length + +**/ +UINT16 +EFIAPI +SetDevicePathNodeLength ( + IN OUT VOID *Node, + IN UINTN Length + ) +{ + ASSERT (Node != NULL); + ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB)); + return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length)); +} + +/** + Fills in all the fields of a device path node that is the end of an entire device path. + + Fills in all the fields of a device path node specified by Node so Node represents + the end of an entire device path. The Type field of Node is set to + END_DEVICE_PATH_TYPE, the SubType field of Node is set to + END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to + END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary, + so it is recommended that a function such as WriteUnaligned16() be used to set + the contents of the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + +**/ +VOID +EFIAPI +SetDevicePathEndNode ( + OUT VOID *Node + ) +{ + ASSERT (Node != NULL); + CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath)); +} + +/** + 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 or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathLibDevicePathUtilities->GetDevicePathSize (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by + DevicePath. If DevicePath is NULL, then NULL is returned. + If the memory is successfully allocated, then the + contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer + is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL If DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathLibDevicePathUtilities->DuplicateDevicePath (DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath to a copy of + FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from + SecondDevicePath is retained. The newly created device path is returned. + If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned. + If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned. + If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is + returned. + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. It is the + responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and + SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + return mDevicePathLibDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath); +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. + The end-of-device-path device node is moved after the end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + return mDevicePathLibDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode); +} + +/** + Creates a new device path by appending the specified device path instance to + the specified device path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + return mDevicePathLibDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance); +} + +/** + Creates a copy of the current device path instance and returns a pointer to the + next device path instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + ASSERT (Size != NULL); + return mDevicePathLibDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size); +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + return mDevicePathLibDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength); +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathLibDevicePathUtilities->IsDevicePathMultiInstance (DevicePath); +} + +/** + Retrieves the device path protocol from a handle. + + This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL + is returned. + + @param Handle The handle from which to retrieve the device + path protocol. + + @return The device path protocol from the handle specified by Handle. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} + +/** + Allocates a device path for a file and appends it to an existing device path. + + If Device is a valid device handle that contains a device path protocol, then + a device path for the file specified by FileName is allocated and appended to + the device path associated with the handle Device. The allocated device path + is returned. If Device is NULL or Device is a handle that does not support the + device path protocol, then a device path containing a single device path node + for the file specified by FileName is allocated and returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + If FileName is NULL, then ASSERT(). + If FileName is not aligned on a 16-bit boundary, then ASSERT(). + + @param Device A pointer to a device handle. This parameter + is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return The allocated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + + DevicePath = NULL; + + Size = StrSize (FileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, FileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + if (Device != NULL) { + DevicePath = DevicePathFromHandle (Device); + } + + DevicePath = AppendDevicePath (DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + return DevicePath; +} + +/** + Locate and return the protocol instance identified by the ProtocolGuid. + + @param ProtocolGuid The GUID of the protocol. + + @return A pointer to the protocol instance or NULL when absent. +**/ +VOID * +UefiDevicePathLibLocateProtocol ( + EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + VOID *Protocol; + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + (VOID**) &Protocol + ); + if (EFI_ERROR (Status)) { + return NULL; + } else { + return Protocol; + } +} + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + if (mDevicePathLibDevicePathToText == NULL) { + mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid); + } + if (mDevicePathLibDevicePathToText != NULL) { + return mDevicePathLibDevicePathToText->ConvertDeviceNodeToText (DeviceNode, DisplayOnly, AllowShortcuts); + } else { + return NULL; + } +} + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + if (mDevicePathLibDevicePathToText == NULL) { + mDevicePathLibDevicePathToText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathToTextProtocolGuid); + } + if (mDevicePathLibDevicePathToText != NULL) { + return mDevicePathLibDevicePathToText->ConvertDevicePathToText (DevicePath, DisplayOnly, AllowShortcuts); + } else { + return NULL; + } +} + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +{ + if (mDevicePathLibDevicePathFromText == NULL) { + mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid); + } + if (mDevicePathLibDevicePathFromText != NULL) { + return mDevicePathLibDevicePathFromText->ConvertTextToDeviceNode (TextDeviceNode); + } else { + return NULL; + } +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +{ + if (mDevicePathLibDevicePathFromText == NULL) { + mDevicePathLibDevicePathFromText = UefiDevicePathLibLocateProtocol (&gEfiDevicePathFromTextProtocolGuid); + } + if (mDevicePathLibDevicePathFromText != NULL) { + return mDevicePathLibDevicePathFromText->ConvertTextToDevicePath (TextDevicePath); + } else { + return NULL; + } +} + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf new file mode 100644 index 000000000..dded21df1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf @@ -0,0 +1,56 @@ +## @file +# Instance of Device Path Library based on Device Path Utilities Protocol. +# +# Device Path Library that layers on top of the UEFI 2.0 Device Path Utilities Protocol. +# This library is not available for EFI 1.10 modules. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDevicePathLibDevicePathProtocol + MODULE_UNI_FILE = UefiDevicePathLibDevicePathProtocol.uni + FILE_GUID = 050EB8C6-C12E-4b86-892B-40985E8B3137 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DevicePathLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = DevicePathLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiDevicePathLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + BaseLib + DebugLib + PcdLib + +[Protocols] + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathUtilitiesProtocolGuid ## CONSUMES + gEfiDevicePathToTextProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount ## SOMETIMES_CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiDevicePathUtilitiesProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni new file mode 100644 index 000000000..c9b436f0f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Device Path Library based on Device Path Utilities Protocol. +// +// Device Path Library that layers on top of the UEFI 2.0 Device Path Utilities Protocol. +// This library is not available for EFI 1.10 modules. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Device Path Library based on Device Path Utilities Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "The Device Path Library that layers on top of the UEFI 2.0 Device Path Utilities Protocol. This library is not available for EFI 1.10 modules." + diff --git a/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c new file mode 100644 index 000000000..c3ccf0fe9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c @@ -0,0 +1,167 @@ +/** @file + Entry point to a EFI/DXE driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include + +#include + +#include +#include +#include +#include + + +/** + Unloads an image from memory. + + This function is a callback that a driver registers to do cleanup + when the UnloadImage boot service function is called. + + @param ImageHandle The handle to the image to unload. + + @return Status returned by all unload(). + +**/ +EFI_STATUS +EFIAPI +_DriverUnloadHandler ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + // + // If an UnloadImage() handler is specified, then call it + // + Status = ProcessModuleUnloadList (ImageHandle); + + // + // If the driver specific unload handler does not return an error, then call all of the + // library destructors. If the unload handler returned an error, then the driver can not be + // unloaded, and the library destructors should not be called + // + if (!EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, gST); + } + + // + // Return the status from the driver specific unload handler + // + return Status; +} + + +/** + The entry point of PE/COFF Image for a DXE Driver, DXE Runtime Driver, DXE SMM + Driver, or UEFI Driver. + + This function is the entry point for a DXE Driver, DXE Runtime Driver, DXE SMM Driver, + or UEFI Driver. This function must call ProcessLibraryConstructorList() and + ProcessModuleEntryPointList(). If the return status from ProcessModuleEntryPointList() + is an error status, then ProcessLibraryDestructorList() must be called. The return + value from ProcessModuleEntryPointList() is returned. If _gDriverUnloadImageCount + is greater than zero, then an unload handler must be registered for this image + and the unload handler must invoke ProcessModuleUnloadList(). + If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than + _gUefiDriverRevison, then return EFI_INCOMPATIBLE_VERSION. + + + @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, + DXE SMM Driver, or UEFI Driver. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM + Driver, or UEFI Driver exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than + SystemTable->Hdr.Revision. + @retval Other Return value from ProcessModuleEntryPointList(). + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + if (_gUefiDriverRevision != 0) { + // + // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the driver + // + if (SystemTable->Hdr.Revision < _gUefiDriverRevision) { + return EFI_INCOMPATIBLE_VERSION; + } + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (ImageHandle, SystemTable); + + // + // Install unload handler... + // + if (_gDriverUnloadImageCount != 0) { + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + LoadedImage->Unload = _DriverUnloadHandler; + } + + // + // Call the driver entry point + // + Status = ProcessModuleEntryPointList (ImageHandle, SystemTable); + + // + // If all of the drivers returned errors, then invoke all of the library destructors + // + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, SystemTable); + } + + // + // Return the cummalative return status code from all of the driver entry points + // + return Status; +} + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + This function is required to call _ModuleEntryPoint() passing in ImageHandle, + and SystemTable. + + @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, DXE + SMM Driver, or UEFI Driver. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM + Driver, or UEFI Driver exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than + SystemTable->Hdr.Revision. + @retval Other Return value from ProcessModuleEntryPointList(). +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return _ModuleEntryPoint (ImageHandle, SystemTable); +} diff --git a/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf new file mode 100644 index 000000000..1d9a8cc1a --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf @@ -0,0 +1,62 @@ +## @file +# Module entry point library for UEFI driver, DXE driver and SMM driver. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDriverEntryPoint + MODULE_UNI_FILE = UefiDriverEntryPoint.uni + FILE_GUID = 331deb15-454b-48d8-9b74-70d01f3f3556 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER SMM_CORE DXE_SMM_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DriverEntryPoint.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + DebugLib + BaseLib + + +[Protocols] + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + + +# +# For UEFI drivers, these architectural protocols defined in PI 1.0 spec need +# to be appended and merged to the final dependency section. +# +[Depex.common.UEFI_DRIVER] + gEfiBdsArchProtocolGuid AND + gEfiCpuArchProtocolGuid AND + gEfiMetronomeArchProtocolGuid AND + gEfiMonotonicCounterArchProtocolGuid AND + gEfiRealTimeClockArchProtocolGuid AND + gEfiResetArchProtocolGuid AND + gEfiRuntimeArchProtocolGuid AND + gEfiSecurityArchProtocolGuid AND + gEfiTimerArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiWatchdogTimerArchProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni new file mode 100644 index 000000000..6667c378f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni @@ -0,0 +1,16 @@ +// /** @file +// Module entry point library for UEFI driver, DXE driver and SMM driver. +// +// Module entry point library for UEFI driver, DXE driver and SMM driver. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver." + diff --git a/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c new file mode 100644 index 000000000..ab34e6ccd --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c @@ -0,0 +1,1281 @@ +/** @file + Provides interface to EFI_FILE_HANDLE functionality. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +CONST UINT16 gUnicodeFileTag = EFI_UNICODE_BYTE_ORDER_MARK; + +#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes) +#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN) + +/** + This function will retrieve the information about the file for the handle + specified and store it in allocated pool memory. + + This function allocates a buffer to store the file's information. It is the + caller's responsibility to free the buffer + + @param FileHandle The file handle of the file for which information is + being requested. + + @retval NULL information could not be retrieved. + + @return the information about the file +**/ +EFI_FILE_INFO* +EFIAPI +FileHandleGetInfo ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_FILE_INFO *FileInfo; + UINTN FileInfoSize; + EFI_STATUS Status; + + if (FileHandle == NULL) { + return (NULL); + } + + // + // Get the required size to allocate + // + FileInfoSize = 0; + FileInfo = NULL; + Status = FileHandle->GetInfo(FileHandle, + &gEfiFileInfoGuid, + &FileInfoSize, + NULL); + if (Status == EFI_BUFFER_TOO_SMALL){ + // + // error is expected. getting size to allocate + // + FileInfo = AllocateZeroPool(FileInfoSize); + if (FileInfo != NULL) { + // + // now get the information + // + Status = FileHandle->GetInfo(FileHandle, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo); + // + // if we got an error free the memory and return NULL + // + if (EFI_ERROR(Status)) { + FreePool(FileInfo); + FileInfo = NULL; + } + } + } + return (FileInfo); +} + +/** + This function sets the information about the file for the opened handle + specified. + + @param[in] FileHandle The file handle of the file for which information + is being set. + + @param[in] FileInfo The information to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid. + @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleSetInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ) +{ + + if (FileHandle == NULL || FileInfo == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Set the info + // + return (FileHandle->SetInfo(FileHandle, + &gEfiFileInfoGuid, + (UINTN)FileInfo->Size, + (EFI_FILE_INFO*)FileInfo)); +} + +/** + This function reads information from an opened file. + + If FileHandle is not a directory, the function reads the requested number of + bytes from the file at the file's current position and returns them in Buffer. + If the read goes beyond the end of the file, the read length is truncated to the + end of the file. The file's current position is increased by the number of bytes + returned. If FileHandle is a directory, the function reads the directory entry + at the file's current position and returns the entry in Buffer. If the Buffer + is not large enough to hold the current directory entry, then + EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. + BufferSize is set to be the size of the buffer needed to read the entry. On + success, the current position is updated to the next directory entry. If there + are no more directory entries, the read returns a zero-length buffer. + EFI_FILE_INFO is the structure returned as the directory entry. + + @param FileHandle the opened file handle + @param BufferSize on input the size of buffer in bytes. on return + the number of bytes written. + @param Buffer the buffer to put read data into. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required + size. + +**/ +EFI_STATUS +EFIAPI +FileHandleRead( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the read based on EFI_FILE_PROTOCOL + // + return (FileHandle->Read(FileHandle, BufferSize, Buffer)); +} + + +/** + Write data to a file. + + This function writes the specified number of bytes to the file at the current + file position. The current file position is advanced the actual number of bytes + written, which is returned in BufferSize. Partial writes only occur when there + has been a data error during the write attempt (such as "volume space full"). + The file is automatically grown to hold the data if required. Direct writes to + opened directories are not supported. + + @param FileHandle The opened file for writing + @param BufferSize on input the number of bytes in Buffer. On output + the number of bytes written. + @param Buffer the buffer containing data to write is stored. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to an open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write-protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleWrite( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the write based on EFI_FILE_PROTOCOL + // + return (FileHandle->Write(FileHandle, BufferSize, Buffer)); +} + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + +@param FileHandle the file handle to close. + +@retval EFI_SUCCESS the file handle was closed successfully. +**/ +EFI_STATUS +EFIAPI +FileHandleClose ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the Close based on EFI_FILE_PROTOCOL + // + Status = FileHandle->Close(FileHandle); + return Status; +} + +/** + Delete a file and close the handle + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param FileHandle the file handle to delete + + @retval EFI_SUCCESS the file was closed successfully + @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not + deleted + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleDelete ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the Delete based on EFI_FILE_PROTOCOL + // + Status = FileHandle->Delete(FileHandle); + return Status; +} + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only + absolute positioning is supported, and seeking past the end of the file is + allowed (a subsequent write would grow the file). Seeking to position + 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. + If FileHandle is a directory, the only position that may be set is zero. This + has the effect of starting the read process of the directory entries over. + + @param FileHandle The file handle on which the position is being set + @param Position Byte position from beginning of file + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on + directories. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleSetPosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Position + ) +{ + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the SetPosition based on EFI_FILE_PROTOCOL + // + return (FileHandle->SetPosition(FileHandle, Position)); +} + +/** + Gets a file's current position + + This function retrieves the current file position for the file handle. For + directories, the current file position has no meaning outside of the file + system driver and as such the operation is not supported. An error is returned + if FileHandle is a directory. + + @param FileHandle The open file handle on which to get the position. + @param Position Byte position from beginning of file. + + @retval EFI_SUCCESS the operation completed successfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED the request is not valid on directories. +**/ +EFI_STATUS +EFIAPI +FileHandleGetPosition ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ) +{ + if (Position == NULL || FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the GetPosition based on EFI_FILE_PROTOCOL + // + return (FileHandle->GetPosition(FileHandle, Position)); +} +/** + Flushes data on a file + + This function flushes all modified data associated with a file to a device. + + @param FileHandle The file handle on which to flush data + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. +**/ +EFI_STATUS +EFIAPI +FileHandleFlush ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Perform the Flush based on EFI_FILE_PROTOCOL + // + return (FileHandle->Flush(FileHandle)); +} + +/** + Function to determine if a given handle is a directory handle. + + Open the file information on the DirHandle and verify that the Attribute + includes EFI_FILE_DIRECTORY bit set. + + @param[in] DirHandle Handle to open file. + + @retval EFI_SUCCESS DirHandle is a directory. + @retval EFI_INVALID_PARAMETER DirHandle is NULL. + The file information returns from FileHandleGetInfo is NULL. + @retval EFI_NOT_FOUND DirHandle is not a directory. +**/ +EFI_STATUS +EFIAPI +FileHandleIsDirectory ( + IN EFI_FILE_HANDLE DirHandle + ) +{ + EFI_FILE_INFO *DirInfo; + + if (DirHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // get the file information for DirHandle + // + DirInfo = FileHandleGetInfo (DirHandle); + + // + // Parse DirInfo + // + if (DirInfo == NULL) { + // + // We got nothing... + // + return (EFI_INVALID_PARAMETER); + } + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + // + // Attributes say this is not a directory + // + FreePool (DirInfo); + return (EFI_NOT_FOUND); + } + // + // all good... + // + FreePool (DirInfo); + return (EFI_SUCCESS); +} + +/** Retrieve first entry from a directory. + + This function takes an open directory handle and gets information from the + first entry in the directory. A buffer is allocated to contain + the information and a pointer to the buffer is returned in *Buffer. The + caller can use FileHandleFindNextFile() to get subsequent directory entries. + + The buffer will be freed by FileHandleFindNextFile() when the last directory + entry is read. Otherwise, the caller must free the buffer, using FreePool, + when finished with it. + + @param[in] DirHandle The file handle of the directory to search. + @param[out] Buffer The pointer to pointer to buffer for file's information. + + @retval EFI_SUCCESS Found the first file. + @retval EFI_NOT_FOUND Cannot find the directory. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @return Others status of FileHandleGetInfo, FileHandleSetPosition, + or FileHandleRead +**/ +EFI_STATUS +EFIAPI +FileHandleFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (Buffer == NULL || DirHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // verify that DirHandle is a directory + // + Status = FileHandleIsDirectory(DirHandle); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Allocate a buffer sized to struct size + enough for the string at the end + // + BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; + *Buffer = AllocateZeroPool(BufferSize); + if (*Buffer == NULL){ + return (EFI_OUT_OF_RESOURCES); + } + + // + // reset to the beginning of the directory + // + Status = FileHandleSetPosition(DirHandle, 0); + if (EFI_ERROR(Status)) { + FreePool(*Buffer); + *Buffer = NULL; + return (Status); + } + + // + // read in the info about the first file + // + Status = FileHandleRead (DirHandle, &BufferSize, *Buffer); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + if (EFI_ERROR(Status) || BufferSize == 0) { + FreePool(*Buffer); + *Buffer = NULL; + if (BufferSize == 0) { + return (EFI_NOT_FOUND); + } + return (Status); + } + return (EFI_SUCCESS); +} + +/** Retrieve next entries from a directory. + + To use this function, the caller must first call the FileHandleFindFirstFile() + function to get the first directory entry. Subsequent directory entries are + retrieved by using the FileHandleFindNextFile() function. This function can + be called several times to get each entry from the directory. If the call of + FileHandleFindNextFile() retrieved the last directory entry, the next call of + this function will set *NoFile to TRUE and free the buffer. + + @param[in] DirHandle The file handle of the directory. + @param[out] Buffer The pointer to buffer for file's information. + @param[out] NoFile The pointer to boolean when last file is found. + + @retval EFI_SUCCESS Found the next file, or reached last file + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. +**/ +EFI_STATUS +EFIAPI +FileHandleFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (DirHandle == NULL || Buffer == NULL || NoFile == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // This BufferSize MUST stay equal to the originally allocated one in GetFirstFile + // + BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; + + // + // read in the info about the next file + // + Status = FileHandleRead (DirHandle, &BufferSize, Buffer); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // If we read 0 bytes (but did not have erros) we already read in the last file. + // + if (BufferSize == 0) { + FreePool(Buffer); + *NoFile = TRUE; + } + + return (EFI_SUCCESS); +} + +/** + Retrieve the size of a file. + + This function extracts the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param[in] FileHandle The file handle from which size is retrieved. + @param[out] Size The pointer to size. + + @retval EFI_SUCCESS Operation was completed successfully. + @retval EFI_DEVICE_ERROR Cannot access the file. + @retval EFI_INVALID_PARAMETER FileHandle is NULL. + Size is NULL. +**/ +EFI_STATUS +EFIAPI +FileHandleGetSize ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ) +{ + EFI_FILE_INFO *FileInfo; + + if (FileHandle == NULL || Size == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // get the FileInfo structure + // + FileInfo = FileHandleGetInfo(FileHandle); + if (FileInfo == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // Assign the Size pointer to the correct value + // + *Size = FileInfo->FileSize; + + // + // free the FileInfo memory + // + FreePool(FileInfo); + + return (EFI_SUCCESS); +} + +/** + Set the size of a file. + + This function changes the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param[in] FileHandle The file handle whose size is to be changed. + @param[in] Size The new size. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR Cannot access the file. + @retval EFI_INVALID_PARAMETER FileHandle is NULL. +**/ +EFI_STATUS +EFIAPI +FileHandleSetSize ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Size + ) +{ + EFI_FILE_INFO *FileInfo; + EFI_STATUS Status; + + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // get the FileInfo structure + // + FileInfo = FileHandleGetInfo(FileHandle); + if (FileInfo == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // Assign the FileSize pointer to the new value + // + FileInfo->FileSize = Size; + + Status = FileHandleSetInfo(FileHandle, FileInfo); + // + // free the FileInfo memory + // + FreePool(FileInfo); + + return (Status); +} + +/** + Safely append (on the left) with automatic string resizing given length of Destination and + desired length of copy from Source. + + append the first D characters of Source to the end of Destination, where D is + the lesser of Count and the StrLen() of Source. If appending those D characters + will fit within Destination (whose Size is given as CurrentSize) and + still leave room for a NULL terminator, then those characters are appended, + starting at the original terminating NULL of Destination, and a new terminating + NULL is appended. + + If appending D characters onto Destination will result in a overflow of the size + given in CurrentSize the string will be grown such that the copy can be performed + and CurrentSize will be updated to the new size. + + If Source is NULL, there is nothing to append, just return the current buffer in + Destination. + + if Destination is NULL, then return error + if Destination's current length (including NULL terminator) is already more then + CurrentSize, then ASSERT() + + @param[in, out] Destination The String to append onto + @param[in, out] CurrentSize on call the number of bytes in Destination. On + return possibly the new size (still in bytes). if NULL + then allocate whatever is needed. + @param[in] Source The String to append from + @param[in] Count Maximum number of characters to append. if 0 then + all are appended. + + @return Destination return the resultant string. +**/ +CHAR16* +EFIAPI +StrnCatGrowLeft ( + IN OUT CHAR16 **Destination, + IN OUT UINTN *CurrentSize, + IN CONST CHAR16 *Source, + IN UINTN Count + ) +{ + UINTN DestinationStartSize; + UINTN NewSize; + UINTN CopySize; + + if (Destination == NULL) { + return (NULL); + } + + // + // If there's nothing to do then just return Destination + // + if (Source == NULL) { + return (*Destination); + } + + // + // allow for NULL pointers address as Destination + // + if (*Destination != NULL) { + ASSERT(CurrentSize != 0); + DestinationStartSize = StrSize(*Destination); + ASSERT(DestinationStartSize <= *CurrentSize); + } else { + DestinationStartSize = 0; +// ASSERT(*CurrentSize == 0); + } + + // + // Append all of Source? + // + if (Count == 0) { + Count = StrSize(Source); + } + + // + // Test and grow if required + // + if (CurrentSize != NULL) { + NewSize = *CurrentSize; + while (NewSize < (DestinationStartSize + Count)) { + NewSize += 2 * Count; + } + *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination); + *CurrentSize = NewSize; + } else { + *Destination = AllocateZeroPool(Count+sizeof(CHAR16)); + } + if (*Destination == NULL) { + return NULL; + } + + CopySize = StrSize(*Destination); + CopyMem((*Destination)+((Count-2)/sizeof(CHAR16)), *Destination, CopySize); + CopyMem(*Destination, Source, Count-2); + return (*Destination); +} + +/** + Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the + directory 'stack'. If the file is a directory, then append the '\' char at the + end of name string. If it's not a directory, then the last '\' should not be + added. + + if Handle is NULL, return EFI_INVALID_PARAMETER + + @param[in] Handle Handle to the Directory or File to create path to. + @param[out] FullFileName pointer to pointer to generated full file name. It + is the responsibility of the caller to free this memory + with a call to FreePool(). + @retval EFI_SUCCESS the operation was sucessful and the FullFileName is valid. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER FullFileName was NULL. + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileHandleGetFileName ( + IN CONST EFI_FILE_HANDLE Handle, + OUT CHAR16 **FullFileName + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_FILE_HANDLE CurrentHandle; + EFI_FILE_HANDLE NextHigherHandle; + EFI_FILE_INFO *FileInfo; + + Size = 0; + + // + // Check our parameters + // + if (FullFileName == NULL || Handle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + *FullFileName = NULL; + CurrentHandle = NULL; + + Status = Handle->Open(Handle, &CurrentHandle, L".", EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR(Status)) { + // + // Reverse out the current directory on the device + // + for (;;) { + FileInfo = FileHandleGetInfo(CurrentHandle); + if (FileInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } else { + // + // Prepare to move to the parent directory. + // Also determine whether CurrentHandle refers to the Root directory. + // + Status = CurrentHandle->Open (CurrentHandle, &NextHigherHandle, L"..", EFI_FILE_MODE_READ, 0); + // + // We got info... do we have a name? if yes precede the current path with it... + // + if ((StrLen (FileInfo->FileName) == 0) || EFI_ERROR (Status)) { + // + // Both FileInfo->FileName being '\0' and EFI_ERROR() suggest that + // CurrentHandle refers to the Root directory. As this loop ensures + // FullFileName is starting with '\\' at all times, signal success + // and exit the loop. + // While FileInfo->FileName could theoretically be a value other than + // '\0' or '\\', '\\' is guaranteed to be supported by the + // specification and hence its value can safely be ignored. + // + Status = EFI_SUCCESS; + if (*FullFileName == NULL) { + ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); + *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); + } + FreePool(FileInfo); + break; + } else { + if (*FullFileName == NULL) { + ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); + *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); + } + ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); + *FullFileName = StrnCatGrowLeft(FullFileName, &Size, FileInfo->FileName, 0); + *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); + FreePool(FileInfo); + } + } + + FileHandleClose(CurrentHandle); + // + // Move to the parent directory + // + CurrentHandle = NextHigherHandle; + } + } else if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); + *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); + } + + if (*FullFileName != NULL && + (*FullFileName)[StrLen(*FullFileName) - 1] == L'\\' && + StrLen(*FullFileName) > 1 && + FileHandleIsDirectory(Handle) == EFI_NOT_FOUND + ) { + (*FullFileName)[StrLen(*FullFileName) - 1] = CHAR_NULL; + } + + if (CurrentHandle != NULL) { + CurrentHandle->Close (CurrentHandle); + } + + if (EFI_ERROR(Status) && *FullFileName != NULL) { + FreePool(*FullFileName); + } + + return (Status); +} + +/** + Function to read a single line from a file. The \n is not included in the returned + buffer. The returned buffer must be callee freed. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle FileHandle to read from. + @param[in, out] Ascii Boolean value for indicating whether the file is Ascii (TRUE) or UCS2 (FALSE); + + @return The line of text from the file. + + @sa FileHandleReadLine +**/ +CHAR16* +EFIAPI +FileHandleReturnLine( + IN EFI_FILE_HANDLE Handle, + IN OUT BOOLEAN *Ascii + ) +{ + CHAR16 *RetVal; + UINTN Size; + EFI_STATUS Status; + + Size = 0; + RetVal = NULL; + + Status = FileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii); + if (Status == EFI_BUFFER_TOO_SMALL) { + RetVal = AllocateZeroPool(Size); + Status = FileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii); + } + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status) && (RetVal != NULL)) { + FreePool(RetVal); + RetVal = NULL; + } + return (RetVal); +} + +/** + Function to read a single line (up to but not including the \n) from a file. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + The function will not return the \r and \n character in buffer. When an empty line is + read a CHAR_NULL character will be returned in buffer. + + @param[in] Handle FileHandle to read from. + @param[in, out] Buffer The pointer to buffer to read into. + @param[in, out] Size The pointer to number of bytes in Buffer. + @param[in] Truncate If the buffer is large enough, this has no effect. + If the buffer is is too small and Truncate is TRUE, + the line will be truncated. + If the buffer is is too small and Truncate is FALSE, + then no read will occur. + + @param[in, out] Ascii Boolean value for indicating whether the file is + Ascii (TRUE) or UCS2 (FALSE). + + @retval EFI_SUCCESS The operation was successful. The line is stored in + Buffer. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER Size was NULL. + @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line. + Size was updated to the minimum space required. + @sa FileHandleRead +**/ +EFI_STATUS +EFIAPI +FileHandleReadLine( + IN EFI_FILE_HANDLE Handle, + IN OUT CHAR16 *Buffer, + IN OUT UINTN *Size, + IN BOOLEAN Truncate, + IN OUT BOOLEAN *Ascii + ) +{ + EFI_STATUS Status; + CHAR16 CharBuffer; + UINT64 FileSize; + UINTN CharSize; + UINTN CountSoFar; + UINTN CrCount; + UINTN OldSize; + UINT64 OriginalFilePosition; + + if (Handle == NULL + ||Size == NULL + ||(Buffer==NULL&&*Size!=0) + ){ + return (EFI_INVALID_PARAMETER); + } + + if (Buffer != NULL && *Size != 0) { + *Buffer = CHAR_NULL; + } + + Status = FileHandleGetSize (Handle, &FileSize); + if (EFI_ERROR (Status)) { + return Status; + } else if (FileSize == 0) { + *Ascii = TRUE; + return EFI_SUCCESS; + } + + FileHandleGetPosition(Handle, &OriginalFilePosition); + if (OriginalFilePosition == 0) { + CharSize = sizeof(CHAR16); + Status = FileHandleRead(Handle, &CharSize, &CharBuffer); + ASSERT_EFI_ERROR(Status); + if (CharBuffer == gUnicodeFileTag) { + *Ascii = FALSE; + } else { + *Ascii = TRUE; + FileHandleSetPosition(Handle, OriginalFilePosition); + } + } + + CrCount = 0; + for (CountSoFar = 0;;CountSoFar++){ + CharBuffer = 0; + if (*Ascii) { + CharSize = sizeof(CHAR8); + } else { + CharSize = sizeof(CHAR16); + } + Status = FileHandleRead(Handle, &CharSize, &CharBuffer); + if ( EFI_ERROR(Status) + || CharSize == 0 + || (CharBuffer == L'\n' && !(*Ascii)) + || (CharBuffer == '\n' && *Ascii) + ){ + break; + } else if ( + (CharBuffer == L'\r' && !(*Ascii)) || + (CharBuffer == '\r' && *Ascii) + ) { + CrCount++; + continue; + } + // + // if we have space save it... + // + if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){ + ASSERT(Buffer != NULL); + ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer; + ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL; + } + } + + // + // if we ran out of space tell when... + // + if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){ + OldSize = *Size; + *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16); + if (!Truncate) { + if (Buffer != NULL && OldSize != 0) { + ZeroMem(Buffer, OldSize); + } + FileHandleSetPosition(Handle, OriginalFilePosition); + return (EFI_BUFFER_TOO_SMALL); + } else { + DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine")); + return (EFI_SUCCESS); + } + } + + return (Status); +} + +/** + Function to write a line of text to a file. + + If the file is a Unicode file (with UNICODE file tag) then write the unicode + text. + If the file is an ASCII file then write the ASCII text. + If the size of file is zero (without file tag at the beginning) then write + ASCII text as default. + + @param[in] Handle FileHandle to write to. + @param[in] Buffer Buffer to write, if NULL the function will + take no action and return EFI_SUCCESS. + + @retval EFI_SUCCESS The data was written. + Buffer is NULL. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_OUT_OF_RESOURCES Unable to allocate temporary space for ASCII + string due to out of resources. + + @sa FileHandleWrite +**/ +EFI_STATUS +EFIAPI +FileHandleWriteLine( + IN EFI_FILE_HANDLE Handle, + IN CHAR16 *Buffer + ) +{ + EFI_STATUS Status; + CHAR16 CharBuffer; + UINTN Size; + UINTN Index; + UINTN CharSize; + UINT64 FileSize; + UINT64 OriginalFilePosition; + BOOLEAN Ascii; + CHAR8 *AsciiBuffer; + + if (Buffer == NULL) { + return (EFI_SUCCESS); + } + + if (Handle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Ascii = FALSE; + AsciiBuffer = NULL; + + Status = FileHandleGetPosition(Handle, &OriginalFilePosition); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = FileHandleSetPosition(Handle, 0); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = FileHandleGetSize(Handle, &FileSize); + if (EFI_ERROR(Status)) { + return Status; + } + + if (FileSize == 0) { + Ascii = TRUE; + } else { + CharSize = sizeof (CHAR16); + Status = FileHandleRead (Handle, &CharSize, &CharBuffer); + ASSERT_EFI_ERROR (Status); + if (CharBuffer == gUnicodeFileTag) { + Ascii = FALSE; + } else { + Ascii = TRUE; + } + } + + Status = FileHandleSetPosition(Handle, OriginalFilePosition); + if (EFI_ERROR(Status)) { + return Status; + } + + if (Ascii) { + Size = ( StrSize(Buffer) / sizeof(CHAR16) ) * sizeof(CHAR8); + AsciiBuffer = (CHAR8 *)AllocateZeroPool(Size); + if (AsciiBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + UnicodeStrToAsciiStrS (Buffer, AsciiBuffer, Size); + for (Index = 0; Index < Size; Index++) { + if ((AsciiBuffer[Index] & BIT7) != 0) { + FreePool(AsciiBuffer); + return EFI_INVALID_PARAMETER; + } + } + + Size = AsciiStrSize(AsciiBuffer) - sizeof(CHAR8); + Status = FileHandleWrite(Handle, &Size, AsciiBuffer); + if (EFI_ERROR(Status)) { + FreePool (AsciiBuffer); + return (Status); + } + Size = AsciiStrSize("\r\n") - sizeof(CHAR8); + Status = FileHandleWrite(Handle, &Size, "\r\n"); + } else { + if (OriginalFilePosition == 0) { + Status = FileHandleSetPosition (Handle, sizeof(CHAR16)); + if (EFI_ERROR(Status)) { + return Status; + } + } + Size = StrSize(Buffer) - sizeof(CHAR16); + Status = FileHandleWrite(Handle, &Size, Buffer); + if (EFI_ERROR(Status)) { + return (Status); + } + Size = StrSize(L"\r\n") - sizeof(CHAR16); + Status = FileHandleWrite(Handle, &Size, L"\r\n"); + } + + if (AsciiBuffer != NULL) { + FreePool (AsciiBuffer); + } + return Status; +} + +/** + function to take a formatted argument and print it to a file. + + @param[in] Handle the file handle for the file to write to + @param[in] Format the format argument (see printlib for format specifier) + @param[in] ... the variable arguments for the format + + @retval EFI_SUCCESS the operation was successful + @return other a return value from FileHandleWriteLine + + @sa FileHandleWriteLine +**/ +EFI_STATUS +EFIAPI +FileHandlePrintLine( + IN EFI_FILE_HANDLE Handle, + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + CHAR16 *Buffer; + EFI_STATUS Status; + + // + // Get a buffer to print into + // + Buffer = AllocateZeroPool (PcdGet16 (PcdUefiFileHandleLibPrintBufferSize)); + if (Buffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Print into our buffer + // + VA_START (Marker, Format); + UnicodeVSPrint (Buffer, PcdGet16 (PcdUefiFileHandleLibPrintBufferSize), Format, Marker); + VA_END (Marker); + + // + // Print buffer into file + // + Status = FileHandleWriteLine(Handle, Buffer); + + // + // Cleanup and return + // + FreePool(Buffer); + return (Status); +} + +/** + Function to determine if a FILE_HANDLE is at the end of the file. + + This will NOT work on directories. + + If Handle is NULL, then return False. + + @param[in] Handle the file handle + + @retval TRUE the position is at the end of the file + @retval FALSE the position is not at the end of the file +**/ +BOOLEAN +EFIAPI +FileHandleEof( + IN EFI_FILE_HANDLE Handle + ) +{ + EFI_FILE_INFO *Info; + UINT64 Pos; + BOOLEAN RetVal; + + if (Handle == NULL) { + return (FALSE); + } + + FileHandleGetPosition(Handle, &Pos); + Info = FileHandleGetInfo (Handle); + + if (Info == NULL) { + return (FALSE); + } + + FileHandleSetPosition(Handle, Pos); + + if (Pos == Info->FileSize) { + RetVal = TRUE; + } else { + RetVal = FALSE; + } + + FreePool (Info); + + return (RetVal); +} diff --git a/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf new file mode 100644 index 000000000..e9a5e2d68 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf @@ -0,0 +1,42 @@ +## @file +# Provides interface to shell functionality for shell commands and applications. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiFileHandleLib + MODULE_UNI_FILE = UefiFileHandleLib.uni + FILE_GUID = 9495D344-9D8A-41f3-8D17-E2FD238C4E71 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FileHandleLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiFileHandleLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + PrintLib + PcdLib + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdUefiFileHandleLibPrintBufferSize ## SOMETIMES_CONSUMES diff --git a/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni new file mode 100644 index 000000000..c2ded1890 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni @@ -0,0 +1,20 @@ +// /** @file +// Provides interface to shell functionality for shell commands and applications. +// +// Provides interface to shell functionality for shell commands and applications. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT +#language en-US +"Provides interface to shell functionality for shell commands and applications." + +#string STR_MODULE_DESCRIPTION +#language en-US +"Provides interface to shell functionality for shell commands and applications." + + diff --git a/roms/edk2/MdePkg/Library/UefiLib/Acpi.c b/roms/edk2/MdePkg/Library/UefiLib/Acpi.c new file mode 100644 index 000000000..d8f147bfe --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/Acpi.c @@ -0,0 +1,422 @@ +/** @file + This module provides help function for finding ACPI table. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiLibInternal.h" +#include +#include + +/** + This function scans ACPI table in XSDT/RSDT. + + @param Sdt ACPI XSDT/RSDT. + @param TablePointerSize Size of table pointer: 8(XSDT) or 4(RSDT). + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate + next table, or NULL to locate first table. + @param PreviousTableLocated Pointer to the indicator about whether the + previous returned table could be located, or + NULL if PreviousTable is NULL. + + If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT(). + If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT(). + + @return ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +ScanTableInSDT ( + IN EFI_ACPI_DESCRIPTION_HEADER *Sdt, + IN UINTN TablePointerSize, + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL + OUT BOOLEAN *PreviousTableLocated OPTIONAL + ) +{ + UINTN Index; + UINTN EntryCount; + UINT64 EntryPtr; + UINTN BasePtr; + EFI_ACPI_COMMON_HEADER *Table; + + if (PreviousTableLocated != NULL) { + ASSERT (PreviousTable != NULL); + *PreviousTableLocated = FALSE; + } else { + ASSERT (PreviousTable == NULL); + } + + if (Sdt == NULL) { + return NULL; + } + + EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize; + + BasePtr = (UINTN)(Sdt + 1); + for (Index = 0; Index < EntryCount; Index ++) { + EntryPtr = 0; + CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * TablePointerSize), TablePointerSize); + Table = (EFI_ACPI_COMMON_HEADER *)((UINTN)(EntryPtr)); + if ((Table != NULL) && (Table->Signature == Signature)) { + if (PreviousTable != NULL) { + if (Table == PreviousTable) { + *PreviousTableLocated = TRUE; + } else if (*PreviousTableLocated) { + // + // Return next table. + // + return Table; + } + } else { + // + // Return first table. + // + return Table; + } + + } + } + + return NULL; +} + +/** + To locate FACS in FADT. + + @param Fadt FADT table pointer. + + @return FACS table pointer or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiFacsFromFadt ( + IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt + ) +{ + EFI_ACPI_COMMON_HEADER *Facs; + UINT64 Data64; + + if (Fadt == NULL) { + return NULL; + } + + if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl; + } else { + CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64)); + if (Data64 != 0) { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64; + } else { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl; + } + } + return Facs; +} + +/** + To locate DSDT in FADT. + + @param Fadt FADT table pointer. + + @return DSDT table pointer or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiDsdtFromFadt ( + IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt + ) +{ + EFI_ACPI_COMMON_HEADER *Dsdt; + UINT64 Data64; + + if (Fadt == NULL) { + return NULL; + } + + if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt; + } else { + CopyMem (&Data64, &Fadt->XDsdt, sizeof(UINT64)); + if (Data64 != 0) { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64; + } else { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt; + } + } + return Dsdt; +} + +/** + To locate ACPI table in ACPI ConfigurationTable. + + @param AcpiGuid The GUID used to get ACPI ConfigurationTable. + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate + next table, or NULL to locate first table. + @param PreviousTableLocated Pointer to the indicator to return whether the + previous returned table could be located or not, + or NULL if PreviousTable is NULL. + + If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT(). + If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT(). + If AcpiGuid is NULL, then ASSERT(). + + @return ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiTableInAcpiConfigurationTable ( + IN EFI_GUID *AcpiGuid, + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL + OUT BOOLEAN *PreviousTableLocated OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_ACPI_COMMON_HEADER *Table; + 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; + + if (PreviousTableLocated != NULL) { + ASSERT (PreviousTable != NULL); + *PreviousTableLocated = FALSE; + } else { + ASSERT (PreviousTable == NULL); + } + + Rsdp = NULL; + // + // Get ACPI ConfigurationTable (RSD_PTR) + // + Status = EfiGetSystemConfigurationTable(AcpiGuid, (VOID **)&Rsdp); + if (EFI_ERROR (Status) || (Rsdp == NULL)) { + return NULL; + } + + Table = NULL; + + // + // Search XSDT + // + if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress; + if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate DSDT, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT ( + Xsdt, + sizeof (UINT64), + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiDsdtFromFadt (Fadt); + } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate FACS, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT ( + Xsdt, + sizeof (UINT64), + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiFacsFromFadt (Fadt); + } else { + Table = ScanTableInSDT ( + Xsdt, + sizeof (UINT64), + Signature, + PreviousTable, + PreviousTableLocated + ); + } + } + + if (Table != NULL) { + return Table; + } else if ((PreviousTableLocated != NULL) && + *PreviousTableLocated) { + // + // PreviousTable could be located in XSDT, + // but next table could not be located in XSDT. + // + return NULL; + } + + // + // Search RSDT + // + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress; + if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate DSDT, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT ( + Rsdt, + sizeof (UINT32), + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiDsdtFromFadt (Fadt); + } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate FACS, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT ( + Rsdt, + sizeof (UINT32), + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiFacsFromFadt (Fadt); + } else { + Table = ScanTableInSDT ( + Rsdt, + sizeof (UINT32), + Signature, + PreviousTable, + PreviousTableLocated + ); + } + + return Table; +} + +/** + This function locates next ACPI table in XSDT/RSDT based on Signature and + previous returned Table. + + If PreviousTable is NULL: + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + If PreviousTable is not NULL: + 1. If it could be located in XSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in XSDT in + gEfiAcpi20TableGuid system configuration table. + 2. If it could be located in RSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi20TableGuid system configuration table. + 3. If it could be located in RSDT in gEfiAcpi10TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi10TableGuid system configuration table. + + It's not supported that PreviousTable is not NULL but PreviousTable->Signature + is not same with Signature, NULL will be returned. + + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate next + table, or NULL to locate first table. + + @return Next ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateNextAcpiTable ( + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable OPTIONAL + ) +{ + EFI_ACPI_COMMON_HEADER *Table; + BOOLEAN TempPreviousTableLocated; + BOOLEAN *PreviousTableLocated; + + if (PreviousTable != NULL) { + if (PreviousTable->Signature != Signature) { + // + // PreviousTable->Signature is not same with Signature. + // + return NULL; + } else if ((Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) || + (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) || + (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE)) { + // + // There is only one FADT/DSDT/FACS table, + // so don't try to locate next one. + // + return NULL; + } + + PreviousTableLocated = &TempPreviousTableLocated; + *PreviousTableLocated = FALSE; + } else { + PreviousTableLocated = NULL; + } + + Table = LocateAcpiTableInAcpiConfigurationTable ( + &gEfiAcpi20TableGuid, + Signature, + PreviousTable, + PreviousTableLocated + ); + if (Table != NULL) { + return Table; + } else if ((PreviousTableLocated != NULL) && + *PreviousTableLocated) { + // + // PreviousTable could be located in gEfiAcpi20TableGuid system + // configuration table, but next table could not be located in + // gEfiAcpi20TableGuid system configuration table. + // + return NULL; + } + + return LocateAcpiTableInAcpiConfigurationTable ( + &gEfiAcpi10TableGuid, + Signature, + PreviousTable, + PreviousTableLocated + ); +} + +/** + This function locates first ACPI table in XSDT/RSDT based on Signature. + + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + @param Signature ACPI table signature. + + @return First ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateFirstAcpiTable ( + IN UINT32 Signature + ) +{ + return EfiLocateNextAcpiTable (Signature, NULL); +} diff --git a/roms/edk2/MdePkg/Library/UefiLib/Console.c b/roms/edk2/MdePkg/Library/UefiLib/Console.c new file mode 100644 index 000000000..17ec31c96 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/Console.c @@ -0,0 +1,566 @@ +/** @file + This module provide help function for displaying unicode string. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +#include "UefiLibInternal.h" + +typedef struct { + CHAR16 WChar; + UINT32 Width; +} UNICODE_WIDTH_ENTRY; + +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = { + // + // General script area + // + {(CHAR16)0x1FFF, 1}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all narrow glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x007F, 1}, // C0 controls and basic Latin. 0x0000-0x007F + {(CHAR16)0x00FF, 1}, // C1 controls and Latin-1 support. 0x0080-0x00FF + {(CHAR16)0x017F, 1}, // Latin extended-A. 0x0100-0x017F + {(CHAR16)0x024F, 1}, // Latin extended-B. 0x0180-0x024F + {(CHAR16)0x02AF, 1}, // IPA extensions. 0x0250-0x02AF + {(CHAR16)0x02FF, 1}, // Spacing modifier letters. 0x02B0-0x02FF + {(CHAR16)0x036F, 1}, // Combining diacritical marks. 0x0300-0x036F + {(CHAR16)0x03FF, 1}, // Greek. 0x0370-0x03FF + {(CHAR16)0x04FF, 1}, // Cyrillic. 0x0400-0x04FF + {(CHAR16)0x052F, 0}, // Unassigned. As Armenian in ver3.0. 0x0500-0x052F + {(CHAR16)0x058F, 1}, // Armenian. 0x0530-0x058F + {(CHAR16)0x05FF, 1}, // Hebrew. 0x0590-0x05FF + {(CHAR16)0x06FF, 1}, // Arabic. 0x0600-0x06FF + {(CHAR16)0x08FF, 0}, // Unassigned. 0x0700-0x08FF + {(CHAR16)0x097F, 1}, // Devanagari. 0x0900-0x097F + {(CHAR16)0x09FF, 1}, // Bengali. 0x0980-0x09FF + {(CHAR16)0x0A7F, 1}, // Gurmukhi. 0x0A00-0x0A7F + {(CHAR16)0x0AFF, 1}, // Gujarati. 0x0A80-0x0AFF + {(CHAR16)0x0B7F, 1}, // Oriya. 0x0B00-0x0B7F + {(CHAR16)0x0BFF, 1}, // Tamil. (See page 7-92). 0x0B80-0x0BFF + {(CHAR16)0x0C7F, 1}, // Telugu. 0x0C00-0x0C7F + {(CHAR16)0x0CFF, 1}, // Kannada. (See page 7-100). 0x0C80-0x0CFF + {(CHAR16)0x0D7F, 1}, // Malayalam (See page 7-104). 0x0D00-0x0D7F + {(CHAR16)0x0DFF, 0}, // Unassigned. 0x0D80-0x0DFF + {(CHAR16)0x0E7F, 1}, // Thai. 0x0E00-0x0E7F + {(CHAR16)0x0EFF, 1}, // Lao. 0x0E80-0x0EFF + {(CHAR16)0x0FBF, 1}, // Tibetan. 0x0F00-0x0FBF + {(CHAR16)0x109F, 0}, // Unassigned. 0x0FC0-0x109F + {(CHAR16)0x10FF, 1}, // Georgian. 0x10A0-0x10FF + {(CHAR16)0x11FF, 1}, // Hangul Jamo. 0x1100-0x11FF + {(CHAR16)0x1DFF, 0}, // Unassigned. 0x1200-0x1DFF + {(CHAR16)0x1EFF, 1}, // Latin extended additional. 0x1E00-0x1EFF + {(CHAR16)0x1FFF, 1}, // Greek extended. 0x1F00-0x1FFF + * + */ + + // + // Symbol area + // + {(CHAR16)0x2FFF, 1}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all narrow glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x206F, 1}, // General punctuation. (See page7-154). 0x200-0x206F + {(CHAR16)0x209F, 1}, // Superscripts and subscripts. 0x2070-0x209F + {(CHAR16)0x20CF, 1}, // Currency symbols. 0x20A0-0x20CF + {(CHAR16)0x20FF, 1}, // Combining diacritical marks for symbols. 0x20D0-0x20FF + {(CHAR16)0x214F, 1}, // Letterlike sympbols. 0x2100-0x214F + {(CHAR16)0x218F, 1}, // Number forms. 0x2150-0x218F + {(CHAR16)0x21FF, 1}, // Arrows. 0x2190-0x21FF + {(CHAR16)0x22FF, 1}, // Mathematical operators. 0x2200-0x22FF + {(CHAR16)0x23FF, 1}, // Miscellaneous technical. 0x2300-0x23FF + {(CHAR16)0x243F, 1}, // Control pictures. 0x2400-0x243F + {(CHAR16)0x245F, 1}, // Optical character recognition. 0x2440-0x245F + {(CHAR16)0x24FF, 1}, // Enclosed alphanumerics. 0x2460-0x24FF + {(CHAR16)0x257F, 1}, // Box drawing. 0x2500-0x257F + {(CHAR16)0x259F, 1}, // Block elements. 0x2580-0x259F + {(CHAR16)0x25FF, 1}, // Geometric shapes. 0x25A0-0x25FF + {(CHAR16)0x26FF, 1}, // Miscellaneous symbols. 0x2600-0x26FF + {(CHAR16)0x27BF, 1}, // Dingbats. 0x2700-0x27BF + {(CHAR16)0x2FFF, 0}, // Reserved. 0x27C0-0x2FFF + * + */ + + // + // CJK phonetics and symbol area + // + {(CHAR16)0x33FF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x303F, 2}, // CJK symbols and punctuation. 0x3000-0x303F + {(CHAR16)0x309F, 2}, // Hiragana. 0x3040-0x309F + {(CHAR16)0x30FF, 2}, // Katakana. 0x30A0-0x30FF + {(CHAR16)0x312F, 2}, // Bopomofo. 0x3100-0x312F + {(CHAR16)0x318F, 2}, // Hangul compatibility jamo. 0x3130-0x318F + {(CHAR16)0x319F, 2}, // Kanbun. 0x3190-0x319F + {(CHAR16)0x31FF, 0}, // Reserved. As Bopomofo extended in ver3.0. 0x31A0-0x31FF + {(CHAR16)0x32FF, 2}, // Enclosed CJK letters and months. 0x3200-0x32FF + {(CHAR16)0x33FF, 2}, // CJK compatibility. 0x3300-0x33FF + * + */ + + // + // CJK ideograph area + // + {(CHAR16)0x9FFF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x4DFF, 0}, // Reserved. 0x3400-0x4DBF as CJK unified ideographs + // extension A in ver3.0. 0x3400-0x4DFF + {(CHAR16)0x9FFF, 2}, // CJK unified ideographs. 0x4E00-0x9FFF + * + */ + + // + // Reserved + // + {(CHAR16)0xABFF, 0}, // Reserved. 0xA000-0xA490 as Yi syllables. 0xA490-0xA4D0 + // as Yi radicals in ver3.0. 0xA000-0xABFF + // + // Hangul syllables + // + {(CHAR16)0xD7FF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0xD7A3, 2}, // Hangul syllables. 0xAC00-0xD7A3 + {(CHAR16)0xD7FF, 0}, // Reserved. 0xD7A3-0xD7FF + * + */ + + // + // Surrogates area + // + {(CHAR16)0xDFFF, 0}, // Surrogates, not used now. 0xD800-0xDFFF + + // + // Private use area + // + {(CHAR16)0xF8FF, 0}, // Private use area. 0xE000-0xF8FF + + // + // Compatibility area and specials + // + {(CHAR16)0xFAFF, 2}, // CJK compatibility ideographs. 0xF900-0xFAFF + {(CHAR16)0xFB4F, 1}, // Alphabetic presentation forms. 0xFB00-0xFB4F + {(CHAR16)0xFDFF, 1}, // Arabic presentation forms-A. 0xFB50-0xFDFF + {(CHAR16)0xFE1F, 0}, // Reserved. As variation selectors in ver3.0. 0xFE00-0xFE1F + {(CHAR16)0xFE2F, 1}, // Combining half marks. 0xFE20-0xFE2F + {(CHAR16)0xFE4F, 2}, // CJK compatibility forms. 0xFE30-0xFE4F + {(CHAR16)0xFE6F, 1}, // Small Form Variants. 0xFE50-0xFE6F + {(CHAR16)0xFEFF, 1}, // Arabic presentation forms-B. 0xFE70-0xFEFF + {(CHAR16)0xFFEF, 1}, // Half width and full width forms. 0xFF00-0xFFEF + {(CHAR16)0xFFFF, 0}, // Speicials. 0xFFF0-0xFFFF +}; + +/** + Retrieves the width of a Unicode character. + + This function computes and returns the width of the Unicode character specified + by UnicodeChar. + + @param UnicodeChar A Unicode character. + + @retval 0 The width if UnicodeChar could not be determined. + @retval 1 UnicodeChar is a narrow glyph. + @retval 2 UnicodeChar is a wide glyph. + +**/ +UINTN +EFIAPI +GetGlyphWidth ( + IN CHAR16 UnicodeChar + ) +{ + UINTN Index; + UINTN Low; + UINTN High; + CONST UNICODE_WIDTH_ENTRY *Item; + + Item = NULL; + Low = 0; + High = (sizeof (mUnicodeWidthTable)) / (sizeof (UNICODE_WIDTH_ENTRY)) - 1; + while (Low <= High) { + Index = (Low + High) >> 1; + Item = &(mUnicodeWidthTable[Index]); + if (Index == 0) { + if (UnicodeChar <= Item->WChar) { + break; + } + + return 0; + } + + if (UnicodeChar > Item->WChar) { + Low = Index + 1; + } else if (UnicodeChar <= mUnicodeWidthTable[Index - 1].WChar) { + High = Index - 1; + } else { + // + // Index - 1 < UnicodeChar <= Index. Found + // + break; + } + } + + if (Low <= High) { + return Item->Width; + } + + return 0; +} + +/** + Computes the display length of a Null-terminated Unicode String. + + This function computes and returns the display length of the Null-terminated + Unicode string specified by String. If String is NULL then 0 is returned. If + any of the widths of the Unicode characters in String can not be determined, + then 0 is returned. The display width of String can be computed by summing the + display widths of each Unicode character in String. Unicode characters that + are narrow glyphs have a width of 1, and Unicode characters that are width glyphs + have a width of 2. If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The display length of the Null-terminated Unicode string specified by String. + +**/ +UINTN +EFIAPI +UnicodeStringDisplayLength ( + IN CONST CHAR16 *String + ) +{ + UINTN Length; + UINTN Width; + + if (String == NULL) { + return 0; + } + + Length = 0; + while (*String != 0) { + Width = GetGlyphWidth (*String); + if (Width == 0) { + return 0; + } + + Length += Width; + String++; + } + + return Length; +} + +/** + Count the storage space of a Unicode string. + + This function handles the Unicode string with NARROW_CHAR + and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR + does not count in the resultant output. If a WIDE_CHAR is + hit, then 2 Unicode character will consume an output storage + space with size of CHAR16 till a NARROW_CHAR is hit. + + @param String The input string to be counted. + @param LimitLen Whether need to limit the string length. + @param MaxWidth The max length this function supported. + @param Offset The max index of the string can be show out. + + @return Storage space for the input string. + +**/ +UINTN +UefiLibGetStringWidth ( + IN CHAR16 *String, + IN BOOLEAN LimitLen, + IN UINTN MaxWidth, + OUT UINTN *Offset + ) +{ + UINTN Index; + UINTN Count; + UINTN IncrementValue; + + if (String == NULL) { + return 0; + } + + Index = 0; + Count = 0; + IncrementValue = 1; + + do { + // + // Advance to the null-terminator or to the first width directive + // + for (;(String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); Index++) { + Count = Count + IncrementValue; + + if (LimitLen && Count > MaxWidth) { + break; + } + } + + // + // We hit the null-terminator, we now have a count + // + if (String[Index] == 0) { + break; + } + + if (LimitLen && Count > MaxWidth) { + *Offset = Index; + break; + } + + // + // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed + // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) + // + if (String[Index] == NARROW_CHAR) { + // + // Skip to the next character + // + Index++; + IncrementValue = 1; + } else { + // + // Skip to the next character + // + Index++; + IncrementValue = 2; + } + } while (String[Index] != 0); + + return Count * sizeof (CHAR16); +} + +/** + Draws a dialog box to the console output device specified by + ConOut defined in the EFI_SYSTEM_TABLE and waits for a keystroke + from the console input device specified by ConIn defined in the + EFI_SYSTEM_TABLE. + + If there are no strings in the variable argument list, then ASSERT(). + If all the strings in the variable argument list are empty, then ASSERT(). + + @param[in] Attribute Specifies the foreground and background color of the popup. + @param[out] Key A pointer to the EFI_KEY value of the key that was + pressed. This is an optional parameter that may be NULL. + If it is NULL then no wait for a keypress will be performed. + @param[in] ... The variable argument list that contains pointers to Null- + terminated Unicode strings to display in the dialog box. + The variable argument list is terminated by a NULL. + +**/ +VOID +EFIAPI +CreatePopUp ( + IN UINTN Attribute, + OUT EFI_INPUT_KEY *Key, OPTIONAL + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; + UINTN Columns; + UINTN Rows; + UINTN Column; + UINTN Row; + UINTN NumberOfLines; + UINTN MaxLength; + CHAR16 *String; + UINTN Length; + CHAR16 *Line; + UINTN EventIndex; + CHAR16 *TmpString; + + // + // Determine the length of the longest line in the popup and the the total + // number of lines in the popup + // + VA_START (Args, Key); + MaxLength = 0; + NumberOfLines = 0; + while ((String = VA_ARG (Args, CHAR16 *)) != NULL) { + MaxLength = MAX (MaxLength, UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2); + NumberOfLines++; + } + VA_END (Args); + + // + // If the total number of lines in the popup is zero, then ASSERT() + // + ASSERT (NumberOfLines != 0); + + // + // If the maximum length of all the strings is zero, then ASSERT() + // + ASSERT (MaxLength != 0); + + // + // Cache a pointer to the Simple Text Output Protocol in the EFI System Table + // + ConOut = gST->ConOut; + + // + // Save the current console cursor position and attributes + // + CopyMem (&SavedConsoleMode, ConOut->Mode, sizeof (SavedConsoleMode)); + + // + // Retrieve the number of columns and rows in the current console mode + // + ConOut->QueryMode (ConOut, SavedConsoleMode.Mode, &Columns, &Rows); + + // + // Disable cursor and set the foreground and background colors specified by Attribute + // + ConOut->EnableCursor (ConOut, FALSE); + ConOut->SetAttribute (ConOut, Attribute); + + // + // Limit NumberOfLines to height of the screen minus 3 rows for the box itself + // + NumberOfLines = MIN (NumberOfLines, Rows - 3); + + // + // Limit MaxLength to width of the screen minus 2 columns for the box itself + // + MaxLength = MIN (MaxLength, Columns - 2); + + // + // Compute the starting row and starting column for the popup + // + Row = (Rows - (NumberOfLines + 3)) / 2; + Column = (Columns - (MaxLength + 2)) / 2; + + // + // Allocate a buffer for a single line of the popup with borders and a Null-terminator + // + Line = AllocateZeroPool ((MaxLength + 3) * sizeof (CHAR16)); + ASSERT (Line != NULL); + + // + // Draw top of popup box + // + SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL); + Line[0] = BOXDRAW_DOWN_RIGHT; + Line[MaxLength + 1] = BOXDRAW_DOWN_LEFT; + Line[MaxLength + 2] = L'\0'; + ConOut->SetCursorPosition (ConOut, Column, Row++); + ConOut->OutputString (ConOut, Line); + + // + // Draw middle of the popup with strings + // + VA_START (Args, Key); + while ((String = VA_ARG (Args, CHAR16 *)) != NULL && NumberOfLines > 0) { + SetMem16 (Line, (MaxLength + 2) * 2, L' '); + Line[0] = BOXDRAW_VERTICAL; + Line[MaxLength + 1] = BOXDRAW_VERTICAL; + Line[MaxLength + 2] = L'\0'; + ConOut->SetCursorPosition (ConOut, Column, Row); + ConOut->OutputString (ConOut, Line); + Length = UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2; + if (Length <= MaxLength) { + // + // Length <= MaxLength + // + ConOut->SetCursorPosition (ConOut, Column + 1 + (MaxLength - Length) / 2, Row++); + ConOut->OutputString (ConOut, String); + } else { + // + // Length > MaxLength + // + UefiLibGetStringWidth (String, TRUE, MaxLength, &Length); + TmpString = AllocateZeroPool ((Length + 1) * sizeof (CHAR16)); + ASSERT (TmpString != NULL); + StrnCpyS (TmpString, Length + 1, String, Length - 3); + StrCatS (TmpString, Length + 1, L"..."); + + ConOut->SetCursorPosition (ConOut, Column + 1, Row++); + ConOut->OutputString (ConOut, TmpString); + FreePool (TmpString); + } + NumberOfLines--; + } + VA_END (Args); + + // + // Draw bottom of popup box + // + SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL); + Line[0] = BOXDRAW_UP_RIGHT; + Line[MaxLength + 1] = BOXDRAW_UP_LEFT; + Line[MaxLength + 2] = L'\0'; + ConOut->SetCursorPosition (ConOut, Column, Row++); + ConOut->OutputString (ConOut, Line); + + // + // Free the allocated line buffer + // + FreePool (Line); + + // + // Restore the cursor visibility, position, and attributes + // + ConOut->EnableCursor (ConOut, SavedConsoleMode.CursorVisible); + ConOut->SetCursorPosition (ConOut, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); + ConOut->SetAttribute (ConOut, SavedConsoleMode.Attribute); + + // + // Wait for a keystroke + // + if (Key != NULL) { + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); + if (!EFI_ERROR (Status)) { + break; + } + + // + // If we encounter error, continue to read another key in. + // + if (Status != EFI_NOT_READY) { + continue; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + } + } +} diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c b/roms/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c new file mode 100644 index 000000000..2f8bf8d2b --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c @@ -0,0 +1,2020 @@ +/** @file + Library functions that abstract driver model protocols + installation and uninstallation. + + Copyright (c) 2019, NVIDIA Corporation. All rights reserved. + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiLibInternal.h" + +/** + Installs and completes the initialization of a Driver Binding Protocol instance. + + Installs the Driver Binding Protocol specified by DriverBinding onto the handle + specified by DriverBindingHandle. If DriverBindingHandle is NULL, then DriverBinding + is installed onto a newly created handle. DriverBindingHandle is typically the same + as the driver's ImageHandle, but it can be different if the driver produces multiple + Driver Binding Protocols. + If DriverBinding is NULL, then ASSERT(). + If DriverBinding can not be installed onto a handle, then ASSERT(). + + @param ImageHandle The image handle of the driver. + @param SystemTable The EFI System Table that was passed to the driver's entry point. + @param DriverBinding A Driver Binding Protocol instance that this driver is producing. + @param DriverBindingHandle The handle that DriverBinding is to be installed onto. If this + parameter is NULL, then a new handle is created. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval EFI_OUT_OF_RESOURCES There was not enough system resources to install the protocol. + @retval Others Status from gBS->InstallMultipleProtocolInterfaces(). + +**/ +EFI_STATUS +EFIAPI +EfiLibInstallDriverBinding ( + IN CONST EFI_HANDLE ImageHandle, + IN CONST EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Uninstalls a Driver Binding Protocol instance. + + If DriverBinding is NULL, then ASSERT(). + If DriverBinding can not be uninstalled, then ASSERT(). + + @param DriverBinding A Driver Binding Protocol instance that this driver produced. + + @retval EFI_SUCCESS The protocol uninstallation successfully completed. + @retval Others Status from gBS->UninstallMultipleProtocolInterfaces(). + +**/ +EFI_STATUS +EFIAPI +EfiLibUninstallDriverBinding ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + // + // ASSERT if the call to UninstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Installs and completes the initialization of a Driver Binding Protocol instance and + optionally installs the Component Name, Driver Configuration and Driver Diagnostics Protocols. + + Initializes a driver by installing the Driver Binding Protocol together with the + optional Component Name, optional Driver Configure and optional Driver Diagnostic + Protocols onto the driver's DriverBindingHandle. If DriverBindingHandle is NULL, + then the protocols are installed onto a newly created handle. DriverBindingHandle + is typically the same as the driver's ImageHandle, but it can be different if the + driver produces multiple Driver Binding Protocols. + If DriverBinding is NULL, then ASSERT(). + If the installation fails, then ASSERT(). + + @param ImageHandle The image handle of the driver. + @param SystemTable The EFI System Table that was passed to the driver's entry point. + @param DriverBinding A Driver Binding Protocol instance that this driver is producing. + @param DriverBindingHandle The handle that DriverBinding is to be installed onto. If this + parameter is NULL, then a new handle is created. + @param ComponentName A Component Name Protocol instance that this driver is producing. + @param DriverConfiguration A Driver Configuration Protocol instance that this driver is producing. + @param DriverDiagnostics A Driver Diagnostics Protocol instance that this driver is producing. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + +**/ +EFI_STATUS +EFIAPI +EfiLibInstallAllDriverProtocols ( + IN CONST EFI_HANDLE ImageHandle, + IN CONST EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverConfiguration == NULL) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } + } else { + if (DriverConfiguration == NULL) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } + + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Uninstalls a Driver Binding Protocol instance and optionally uninstalls the + Component Name, Driver Configuration and Driver Diagnostics Protocols. + + If DriverBinding is NULL, then ASSERT(). + If the uninstallation fails, then ASSERT(). + + @param DriverBinding A Driver Binding Protocol instance that this driver produced. + @param ComponentName A Component Name Protocol instance that this driver produced. + @param DriverConfiguration A Driver Configuration Protocol instance that this driver produced. + @param DriverDiagnostics A Driver Diagnostics Protocol instance that this driver produced. + + @retval EFI_SUCCESS The protocol uninstallation successfully completed. + @retval Others Status from gBS->UninstallMultipleProtocolInterfaces(). + +**/ +EFI_STATUS +EFIAPI +EfiLibUninstallAllDriverProtocols ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverConfiguration == NULL) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } + } else { + if (DriverConfiguration == NULL) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } + + // + // ASSERT if the call to UninstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Installs Driver Binding Protocol with optional Component Name and Component Name 2 Protocols. + + Initializes a driver by installing the Driver Binding Protocol together with the + optional Component Name and optional Component Name 2 protocols onto the driver's + DriverBindingHandle. If DriverBindingHandle is NULL, then the protocols are installed + onto a newly created handle. DriverBindingHandle is typically the same as the driver's + ImageHandle, but it can be different if the driver produces multiple Driver Binding Protocols. + If DriverBinding is NULL, then ASSERT(). + If the installation fails, then ASSERT(). + + @param ImageHandle The image handle of the driver. + @param SystemTable The EFI System Table that was passed to the driver's entry point. + @param DriverBinding A Driver Binding Protocol instance that this driver is producing. + @param DriverBindingHandle The handle that DriverBinding is to be installed onto. If this + parameter is NULL, then a new handle is created. + @param ComponentName A Component Name Protocol instance that this driver is producing. + @param ComponentName2 A Component Name 2 Protocol instance that this driver is producing. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + +**/ +EFI_STATUS +EFIAPI +EfiLibInstallDriverBindingComponentName2 ( + IN CONST EFI_HANDLE ImageHandle, + IN CONST EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Uninstalls Driver Binding Protocol with optional Component Name and Component Name 2 Protocols. + + If DriverBinding is NULL, then ASSERT(). + If the uninstallation fails, then ASSERT(). + + @param DriverBinding A Driver Binding Protocol instance that this driver produced. + @param ComponentName A Component Name Protocol instance that this driver produced. + @param ComponentName2 A Component Name 2 Protocol instance that this driver produced. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval Others Status from gBS->UninstallMultipleProtocolInterfaces(). + +**/ +EFI_STATUS +EFIAPI +EfiLibUninstallDriverBindingComponentName2 ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + + // + // ASSERT if the call to UninstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Installs Driver Binding Protocol with optional Component Name, Component Name 2, Driver + Configuration, Driver Configuration 2, Driver Diagnostics, and Driver Diagnostics 2 Protocols. + + Initializes a driver by installing the Driver Binding Protocol together with the optional + Component Name, optional Component Name 2, optional Driver Configuration, optional Driver Configuration 2, + optional Driver Diagnostic, and optional Driver Diagnostic 2 Protocols onto the driver's DriverBindingHandle. + DriverBindingHandle is typically the same as the driver's ImageHandle, but it can be different if the driver + produces multiple Driver Binding Protocols. + If DriverBinding is NULL, then ASSERT(). + If the installation fails, then ASSERT(). + + + @param ImageHandle The image handle of the driver. + @param SystemTable The EFI System Table that was passed to the driver's entry point. + @param DriverBinding A Driver Binding Protocol instance that this driver is producing. + @param DriverBindingHandle The handle that DriverBinding is to be installed onto. If this + parameter is NULL, then a new handle is created. + @param ComponentName A Component Name Protocol instance that this driver is producing. + @param ComponentName2 A Component Name 2 Protocol instance that this driver is producing. + @param DriverConfiguration A Driver Configuration Protocol instance that this driver is producing. + @param DriverConfiguration2 A Driver Configuration Protocol 2 instance that this driver is producing. + @param DriverDiagnostics A Driver Diagnostics Protocol instance that this driver is producing. + @param DriverDiagnostics2 A Driver Diagnostics Protocol 2 instance that this driver is producing. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + +**/ +EFI_STATUS +EFIAPI +EfiLibInstallAllDriverProtocols2 ( + IN CONST EFI_HANDLE ImageHandle, + IN CONST EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION2_PROTOCOL *DriverConfiguration2, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2 OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + if (DriverConfiguration2 == NULL) { + if (DriverConfiguration == NULL) { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } else { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } + } else { + if (DriverConfiguration == NULL) { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } else { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } + } + + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + + +/** + Uninstalls Driver Binding Protocol with optional Component Name, Component Name 2, Driver + Configuration, Driver Configuration 2, Driver Diagnostics, and Driver Diagnostics 2 Protocols. + + If DriverBinding is NULL, then ASSERT(). + If the installation fails, then ASSERT(). + + + @param DriverBinding A Driver Binding Protocol instance that this driver produced. + @param ComponentName A Component Name Protocol instance that this driver produced. + @param ComponentName2 A Component Name 2 Protocol instance that this driver produced. + @param DriverConfiguration A Driver Configuration Protocol instance that this driver produced. + @param DriverConfiguration2 A Driver Configuration Protocol 2 instance that this driver produced. + @param DriverDiagnostics A Driver Diagnostics Protocol instance that this driver produced. + @param DriverDiagnostics2 A Driver Diagnostics Protocol 2 instance that this driver produced. + + @retval EFI_SUCCESS The protocol uninstallation successfully completed. + @retval Others Status from gBS->UninstallMultipleProtocolInterfaces(). + +**/ +EFI_STATUS +EFIAPI +EfiLibUninstallAllDriverProtocols2 ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL + IN CONST EFI_DRIVER_CONFIGURATION2_PROTOCOL *DriverConfiguration2, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics, OPTIONAL + IN CONST EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2 OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + if (DriverConfiguration2 == NULL) { + if (DriverConfiguration == NULL) { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } else { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } + } else { + if (DriverConfiguration == NULL) { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } else { + if (DriverDiagnostics == NULL || FeaturePcdGet(PcdDriverDiagnosticsDisable)) { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } else { + if (DriverDiagnostics2 == NULL || FeaturePcdGet(PcdDriverDiagnostics2Disable)) { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + NULL + ); + } + } + } else { + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + &gEfiDriverConfigurationProtocolGuid, DriverConfiguration, + &gEfiDriverConfiguration2ProtocolGuid, DriverConfiguration2, + &gEfiDriverDiagnosticsProtocolGuid, DriverDiagnostics, + &gEfiDriverDiagnostics2ProtocolGuid, DriverDiagnostics2, + NULL + ); + } + } + } + } + } + } + + // + // ASSERT if the call to UninstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiLib.c b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.c new file mode 100644 index 000000000..07c45d1e9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.c @@ -0,0 +1,2013 @@ +/** @file + The UEFI Library provides functions and macros that simplify the development of + UEFI Drivers and UEFI Applications. These functions and macros help manage EFI + events, build simple locks utilizing EFI Task Priority Levels (TPLs), install + EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, + and print messages on the console output and standard error devices. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiLibInternal.h" + +/** + Empty constructor function that is required to resolve dependencies between + libraries. + + ** DO NOT REMOVE ** + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor executed correctly. + +**/ +EFI_STATUS +EFIAPI +UefiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + +/** + Compare whether two names of languages are identical. + + @param Language1 Name of language 1. + @param Language2 Name of language 2. + + @retval TRUE Language 1 and language 2 are the same. + @retval FALSE Language 1 and language 2 are not the same. + +**/ +BOOLEAN +CompareIso639LanguageCode ( + IN CONST CHAR8 *Language1, + IN CONST CHAR8 *Language2 + ) +{ + UINT32 Name1; + UINT32 Name2; + + Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1); + Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2); + + return (BOOLEAN) (Name1 == Name2); +} + +/** + Retrieves a pointer to the system configuration table from the EFI System Table + based on a specified GUID. + + This function searches the list of configuration tables stored in the EFI System Table + for a table with a GUID that matches TableGuid. If a match is found, then a pointer to + the configuration table is returned in Table., and EFI_SUCCESS is returned. If a matching GUID + is not found, then EFI_NOT_FOUND is returned. + If TableGuid is NULL, then ASSERT(). + If Table is NULL, then ASSERT(). + + @param TableGuid The pointer to table's GUID type. + @param Table The pointer to the table associated with TableGuid in the EFI System Table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found. + +**/ +EFI_STATUS +EFIAPI +EfiGetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + OUT VOID **Table + ) +{ + EFI_SYSTEM_TABLE *SystemTable; + UINTN Index; + + ASSERT (TableGuid != NULL); + ASSERT (Table != NULL); + + SystemTable = gST; + *Table = NULL; + for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { + if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) { + *Table = SystemTable->ConfigurationTable[Index].VendorTable; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Creates and returns a notification event and registers that event with all the protocol + instances specified by ProtocolGuid. + + This function causes the notification function to be executed for every protocol of type + ProtocolGuid instance that exists in the system when this function is invoked. If there are + no instances of ProtocolGuid in the handle database at the time this function is invoked, + then the notification function is still executed one time. In addition, every time a protocol + of type ProtocolGuid instance is installed or reinstalled, the notification function is also + executed. This function returns the notification event that was created. + If ProtocolGuid is NULL, then ASSERT(). + If NotifyTpl is not a legal TPL value, then ASSERT(). + If NotifyFunction is NULL, then ASSERT(). + If Registration is NULL, then ASSERT(). + + + @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + This value is passed to LocateHandle() to obtain new handles that + have been added that support the ProtocolGuid-specified protocol. + + @return The notification event that was created. + +**/ +EFI_EVENT +EFIAPI +EfiCreateProtocolNotifyEvent( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, OPTIONAL + OUT VOID **Registration + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + ASSERT (ProtocolGuid != NULL); + ASSERT (NotifyFunction != NULL); + ASSERT (Registration != NULL); + + // + // Create the event + // + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifications on this event + // + + Status = gBS->RegisterProtocolNotify ( + ProtocolGuid, + Event, + Registration + ); + + ASSERT_EFI_ERROR (Status); + + // + // Kick the event so we will perform an initial pass of + // current installed drivers + // + + gBS->SignalEvent (Event); + return Event; +} + +/** + Creates a named event that can be signaled with EfiNamedEventSignal(). + + This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext. + This event is signaled with EfiNamedEventSignal(). This provides the ability for one or more + listeners on the same event named by the GUID specified by Name. + If Name is NULL, then ASSERT(). + If NotifyTpl is not a legal TPL value, then ASSERT(). + If NotifyFunction is NULL, then ASSERT(). + + @param Name Supplies the GUID name of the event. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS A named event was created. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventListen ( + IN CONST EFI_GUID *Name, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN CONST VOID *NotifyContext, OPTIONAL + OUT VOID *Registration OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + VOID *RegistrationLocal; + + ASSERT (Name != NULL); + ASSERT (NotifyFunction != NULL); + ASSERT (NotifyTpl <= TPL_HIGH_LEVEL); + + // + // Create event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + (VOID *) NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // The Registration is not optional to RegisterProtocolNotify(). + // To make it optional to EfiNamedEventListen(), may need to substitute with a local. + // + if (Registration != NULL) { + RegistrationLocal = Registration; + } else { + RegistrationLocal = &RegistrationLocal; + } + + // + // Register for an installation of protocol interface + // + + Status = gBS->RegisterProtocolNotify ( + (EFI_GUID *) Name, + Event, + RegistrationLocal + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Signals a named event created with EfiNamedEventListen(). + + This function signals the named event specified by Name. The named event must have been + created with EfiNamedEventListen(). + If Name is NULL, then ASSERT(). + + @param Name Supplies the GUID name of the event. + + @retval EFI_SUCCESS A named event was signaled. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventSignal ( + IN CONST EFI_GUID *Name + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + ASSERT(Name != NULL); + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + (EFI_GUID *) Name, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->UninstallProtocolInterface ( + Handle, + (EFI_GUID *) Name, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Signals an event group by placing a new event in the group temporarily and + signaling it. + + @param[in] EventGroup Supplies the unique identifier of the event + group to signal. + + @retval EFI_SUCCESS The event group was signaled successfully. + @retval EFI_INVALID_PARAMETER EventGroup is NULL. + @return Error codes that report problems about event + creation or signaling. +**/ +EFI_STATUS +EFIAPI +EfiEventGroupSignal ( + IN CONST EFI_GUID *EventGroup + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + if (EventGroup == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + EfiEventEmptyFunction, + NULL, + EventGroup, + &Event + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SignalEvent (Event); + gBS->CloseEvent (Event); + + return Status; +} + +/** + An empty function that can be used as NotifyFunction parameter of + CreateEvent() or CreateEventEx(). + + @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 +EfiEventEmptyFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + +/** + Returns the current TPL. + + This function returns the current TPL. There is no EFI service to directly + retrieve the current TPL. Instead, the RaiseTPL() function is used to raise + the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level + can then immediately be restored back to the current TPL level with a call + to RestoreTPL(). + + @return The current TPL. + +**/ +EFI_TPL +EFIAPI +EfiGetCurrentTpl ( + VOID + ) +{ + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + gBS->RestoreTPL (Tpl); + + return Tpl; +} + + +/** + Initializes a basic mutual exclusion lock. + + This function initializes a basic mutual exclusion lock to the released state + and returns the lock. Each lock provides mutual exclusion access at its task + priority level. Since there is no preemption or multiprocessor support in EFI, + acquiring the lock only consists of raising to the locks TPL. + If Lock is NULL, then ASSERT(). + If Priority is not a valid TPL value, then ASSERT(). + + @param Lock A pointer to the lock data structure to initialize. + @param Priority EFI TPL is associated with the lock. + + @return The lock. + +**/ +EFI_LOCK * +EFIAPI +EfiInitializeLock ( + IN OUT EFI_LOCK *Lock, + IN EFI_TPL Priority + ) +{ + ASSERT (Lock != NULL); + ASSERT (Priority <= TPL_HIGH_LEVEL); + + Lock->Tpl = Priority; + Lock->OwnerTpl = TPL_APPLICATION; + Lock->Lock = EfiLockReleased ; + return Lock; +} + +/** + Acquires ownership of a lock. + + This function raises the system's current task priority level to the task + priority level of the mutual exclusion lock. Then, it places the lock in the + acquired state. + If Lock is NULL, then ASSERT(). + If Lock is not initialized, then ASSERT(). + If Lock is already in the acquired state, then ASSERT(). + + @param Lock A pointer to the lock to acquire. + +**/ +VOID +EFIAPI +EfiAcquireLock ( + IN EFI_LOCK *Lock + ) +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockReleased); + + Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl); + Lock->Lock = EfiLockAcquired; +} + +/** + Acquires ownership of a lock. + + This function raises the system's current task priority level to the task priority + level of the mutual exclusion lock. Then, it attempts to place the lock in the acquired state. + If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned. + Otherwise, EFI_SUCCESS is returned. + If Lock is NULL, then ASSERT(). + If Lock is not initialized, then ASSERT(). + + @param Lock A pointer to the lock to acquire. + + @retval EFI_SUCCESS The lock was acquired. + @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned. + +**/ +EFI_STATUS +EFIAPI +EfiAcquireLockOrFail ( + IN EFI_LOCK *Lock + ) +{ + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock != EfiLockUninitialized); + + if (Lock->Lock == EfiLockAcquired) { + // + // Lock is already owned, so bail out + // + return EFI_ACCESS_DENIED; + } + + Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl); + + Lock->Lock = EfiLockAcquired; + + return EFI_SUCCESS; +} + +/** + Releases ownership of a lock. + + This function transitions a mutual exclusion lock from the acquired state to + the released state, and restores the system's task priority level to its + previous level. + If Lock is NULL, then ASSERT(). + If Lock is not initialized, then ASSERT(). + If Lock is already in the released state, then ASSERT(). + + @param Lock A pointer to the lock to release. + +**/ +VOID +EFIAPI +EfiReleaseLock ( + IN EFI_LOCK *Lock + ) +{ + EFI_TPL Tpl; + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockAcquired); + + Tpl = Lock->OwnerTpl; + + Lock->Lock = EfiLockReleased; + + gBS->RestoreTPL (Tpl); +} + +/** + Tests whether a controller handle is being managed by a specific driver. + + This function tests whether the driver specified by DriverBindingHandle is + currently managing the controller specified by ControllerHandle. This test + is performed by evaluating if the the protocol specified by ProtocolGuid is + present on ControllerHandle and is was opened by DriverBindingHandle with an + attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. + If ProtocolGuid is NULL, then ASSERT(). + + @param ControllerHandle A handle for a controller to test. + @param DriverBindingHandle Specifies the driver binding handle for the + driver. + @param ProtocolGuid Specifies the protocol that the driver specified + by DriverBindingHandle opens in its Start() + function. + + @retval EFI_SUCCESS ControllerHandle is managed by the driver + specified by DriverBindingHandle. + @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver + specified by DriverBindingHandle. + +**/ +EFI_STATUS +EFIAPI +EfiTestManagedDevice ( + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE DriverBindingHandle, + IN CONST EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + VOID *ManagedInterface; + + ASSERT (ProtocolGuid != NULL); + + Status = gBS->OpenProtocol ( + ControllerHandle, + (EFI_GUID *) ProtocolGuid, + &ManagedInterface, + DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + (EFI_GUID *) ProtocolGuid, + DriverBindingHandle, + ControllerHandle + ); + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Tests whether a child handle is a child device of the controller. + + This function tests whether ChildHandle is one of the children of + ControllerHandle. This test is performed by checking to see if the protocol + specified by ProtocolGuid is present on ControllerHandle and opened by + ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + If ProtocolGuid is NULL, then ASSERT(). + + @param ControllerHandle A handle for a (parent) controller to test. + @param ChildHandle A child handle to test. + @param ProtocolGuid Supplies the protocol that the child controller + opens on its parent controller. + + @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle. + @retval EFI_UNSUPPORTED ChildHandle is not a child of the + ControllerHandle. + +**/ +EFI_STATUS +EFIAPI +EfiTestChildHandle ( + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE ChildHandle, + IN CONST EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + + ASSERT (ProtocolGuid != NULL); + + // + // Retrieve the list of agents that are consuming the specific protocol + // on ControllerHandle. + // + Status = gBS->OpenProtocolInformation ( + ControllerHandle, + (EFI_GUID *) ProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Inspect if ChildHandle is one of the agents. + // + Status = EFI_UNSUPPORTED; + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) && + (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = EFI_SUCCESS; + break; + } + } + + FreePool (OpenInfoBuffer); + return Status; +} + +/** + This function checks the supported languages list for a target language, + This only supports RFC 4646 Languages. + + @param SupportedLanguages The supported languages + @param TargetLanguage The target language + + @retval Returns EFI_SUCCESS if the language is supported, + EFI_UNSUPPORTED otherwise +**/ +EFI_STATUS +EFIAPI +IsLanguageSupported ( + IN CONST CHAR8 *SupportedLanguages, + IN CONST CHAR8 *TargetLanguage + ) +{ + UINTN Index; + while (*SupportedLanguages != 0) { + for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); + if ((AsciiStrnCmp(SupportedLanguages, TargetLanguage, Index) == 0) && (TargetLanguage[Index] == 0)) { + return EFI_SUCCESS; + } + SupportedLanguages += Index; + for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); + } + + return EFI_UNSUPPORTED; +} + +/** + This function looks up a Unicode string in UnicodeStringTable. + + If Language is a member of SupportedLanguages and a Unicode string is found in + UnicodeStringTable that matches the language code specified by Language, then it + is returned in UnicodeString. + + @param Language A pointer to the ISO 639-2 language code for the + Unicode string to look up and return. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. Language + must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string from UnicodeStringTable + that matches the language specified by Language. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found + in the table of Unicode strings UnicodeStringTable, + and it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + @retval EFI_UNSUPPORTED The language specified by Language is not + supported by UnicodeStringTable. + +**/ +EFI_STATUS +EFIAPI +LookupUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + OUT CHAR16 **UnicodeString + ) +{ + // + // Make sure the parameters are valid + // + if (Language == NULL || UnicodeString == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, or the Unicode String Table is empty, then the + // Unicode String specified by Language is not supported by this Unicode String Table + // + if (SupportedLanguages == NULL || UnicodeStringTable == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure Language is in the set of Supported Languages + // + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + + // + // Search the Unicode String Table for the matching Language specifier + // + while (UnicodeStringTable->Language != NULL) { + if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) { + + // + // A matching string was found, so return it + // + *UnicodeString = UnicodeStringTable->UnicodeString; + return EFI_SUCCESS; + } + + UnicodeStringTable++; + } + + return EFI_UNSUPPORTED; + } + + SupportedLanguages += 3; + } + + return EFI_UNSUPPORTED; +} + + + +/** + This function looks up a Unicode string in UnicodeStringTable. + + If Language is a member of SupportedLanguages and a Unicode string is found in + UnicodeStringTable that matches the language code specified by Language, then + it is returned in UnicodeString. + + @param Language A pointer to an ASCII string containing the ISO 639-2 or the + RFC 4646 language code for the Unicode string to look up and + return. If Iso639Language is TRUE, then this ASCII string is + not assumed to be Null-terminated, and only the first three + characters are used. If Iso639Language is FALSE, then this ASCII + string must be Null-terminated. + @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains a + set of ISO 639-2 or RFC 4646 language codes that the Unicode + string table supports. Language must be a member of this set. + If Iso639Language is TRUE, then this string contains one or more + ISO 639-2 language codes with no separator characters. If Iso639Language + is FALSE, then is string contains one or more RFC 4646 language + codes separated by ';'. + @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE + is defined in "Related Definitions". + @param UnicodeString A pointer to the Null-terminated Unicode string from UnicodeStringTable + that matches the language specified by Language. + @param Iso639Language Specifies the supported language code format. If it is TRUE, then + Language and SupportedLanguages follow ISO 639-2 language code format. + Otherwise, they follow RFC 4646 language code format. + + + @retval EFI_SUCCESS The Unicode string that matches the language specified by Language + was found in the table of Unicode strings UnicodeStringTable, and + it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. + @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages. + @retval EFI_UNSUPPORTED The language specified by Language is not supported by UnicodeStringTable. + +**/ +EFI_STATUS +EFIAPI +LookupUnicodeString2 ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + OUT CHAR16 **UnicodeString, + IN BOOLEAN Iso639Language + ) +{ + BOOLEAN Found; + UINTN Index; + CHAR8 *LanguageString; + + // + // Make sure the parameters are valid + // + if (Language == NULL || UnicodeString == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, or the Unicode String Table is empty, then the + // Unicode String specified by Language is not supported by this Unicode String Table + // + if (SupportedLanguages == NULL || UnicodeStringTable == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure Language is in the set of Supported Languages + // + Found = FALSE; + if (Iso639Language) { + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } + } else { + Found = !IsLanguageSupported(Language, SupportedLanguages); + } + + + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + // + // Search the Unicode String Table for the matching Language specifier + // + while (UnicodeStringTable->Language != NULL) { + LanguageString = UnicodeStringTable->Language; + while (0 != *LanguageString) { + for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++); + if (AsciiStrnCmp(LanguageString, Language, Index) == 0) { + *UnicodeString = UnicodeStringTable->UnicodeString; + return EFI_SUCCESS; + } + LanguageString += Index; + for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++); + } + UnicodeStringTable++; + } + + return EFI_UNSUPPORTED; +} + + +/** + This function adds a Unicode string to UnicodeStringTable. + + If Language is a member of SupportedLanguages then UnicodeString is added to + UnicodeStringTable. New buffers are allocated for both Language and + UnicodeString. The contents of Language and UnicodeString are copied into + these new buffers. These buffers are automatically freed when + FreeUnicodeStringTable() is called. + + @param Language A pointer to the ISO 639-2 language code for the Unicode + string to add. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. + Language must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string to add. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found in the table of + Unicode strings UnicodeStringTable, and it was + returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is an empty string. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_ALREADY_STARTED A Unicode string with language Language is + already present in UnicodeStringTable. + @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another + Unicode string to UnicodeStringTable. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + +**/ +EFI_STATUS +EFIAPI +AddUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN OUT EFI_UNICODE_STRING_TABLE **UnicodeStringTable, + IN CONST CHAR16 *UnicodeString + ) +{ + UINTN NumberOfEntries; + EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable; + EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable; + UINTN UnicodeStringLength; + + // + // Make sure the parameter are valid + // + if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, then a Unicode String can not be added + // + if (SupportedLanguages == NULL) { + return EFI_UNSUPPORTED; + } + + // + // If the Unicode String is empty, then a Unicode String can not be added + // + if (UnicodeString[0] == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure Language is a member of SupportedLanguages + // + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + + // + // Determine the size of the Unicode String Table by looking for a NULL Language entry + // + NumberOfEntries = 0; + if (*UnicodeStringTable != NULL) { + OldUnicodeStringTable = *UnicodeStringTable; + while (OldUnicodeStringTable->Language != NULL) { + if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) { + return EFI_ALREADY_STARTED; + } + + OldUnicodeStringTable++; + NumberOfEntries++; + } + } + + // + // Allocate space for a new Unicode String Table. It must hold the current number of + // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table + // marker + // + NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE)); + if (NewUnicodeStringTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If the current Unicode String Table contains any entries, then copy them to the + // newly allocated Unicode String Table. + // + if (*UnicodeStringTable != NULL) { + CopyMem ( + NewUnicodeStringTable, + *UnicodeStringTable, + NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE) + ); + } + + // + // Allocate space for a copy of the Language specifier + // + NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language); + if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) { + FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Compute the length of the Unicode String + // + for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++) + ; + + // + // Allocate space for a copy of the Unicode String + // + NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool ( + (UnicodeStringLength + 1) * sizeof (CHAR16), + UnicodeString + ); + if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) { + FreePool (NewUnicodeStringTable[NumberOfEntries].Language); + FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Mark the end of the Unicode String Table + // + NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL; + NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL; + + // + // Free the old Unicode String Table + // + if (*UnicodeStringTable != NULL) { + FreePool (*UnicodeStringTable); + } + + // + // Point UnicodeStringTable at the newly allocated Unicode String Table + // + *UnicodeStringTable = NewUnicodeStringTable; + + return EFI_SUCCESS; + } + + SupportedLanguages += 3; + } + + return EFI_UNSUPPORTED; +} + + +/** + This function adds the Null-terminated Unicode string specified by UnicodeString + to UnicodeStringTable. + + If Language is a member of SupportedLanguages then UnicodeString is added to + UnicodeStringTable. New buffers are allocated for both Language and UnicodeString. + The contents of Language and UnicodeString are copied into these new buffers. + These buffers are automatically freed when EfiLibFreeUnicodeStringTable() is called. + + @param Language A pointer to an ASCII string containing the ISO 639-2 or + the RFC 4646 language code for the Unicode string to add. + If Iso639Language is TRUE, then this ASCII string is not + assumed to be Null-terminated, and only the first three + chacters are used. If Iso639Language is FALSE, then this + ASCII string must be Null-terminated. + @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains + a set of ISO 639-2 or RFC 4646 language codes that the Unicode + string table supports. Language must be a member of this set. + If Iso639Language is TRUE, then this string contains one or more + ISO 639-2 language codes with no separator characters. + If Iso639Language is FALSE, then is string contains one or more + RFC 4646 language codes separated by ';'. + @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE + is defined in "Related Definitions". + @param UnicodeString A pointer to the Unicode string to add. + @param Iso639Language Specifies the supported language code format. If it is TRUE, + then Language and SupportedLanguages follow ISO 639-2 language code format. + Otherwise, they follow RFC 4646 language code format. + + @retval EFI_SUCCESS The Unicode string that matches the language specified by + Language was found in the table of Unicode strings UnicodeStringTable, + and it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is an empty string. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_ALREADY_STARTED A Unicode string with language Language is already present in + UnicodeStringTable. + @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another Unicode string UnicodeStringTable. + @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages. + +**/ +EFI_STATUS +EFIAPI +AddUnicodeString2 ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN OUT EFI_UNICODE_STRING_TABLE **UnicodeStringTable, + IN CONST CHAR16 *UnicodeString, + IN BOOLEAN Iso639Language + ) +{ + UINTN NumberOfEntries; + EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable; + EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable; + UINTN UnicodeStringLength; + BOOLEAN Found; + UINTN Index; + CHAR8 *LanguageString; + + // + // Make sure the parameter are valid + // + if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, then a Unicode String can not be added + // + if (SupportedLanguages == NULL) { + return EFI_UNSUPPORTED; + } + + // + // If the Unicode String is empty, then a Unicode String can not be added + // + if (UnicodeString[0] == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure Language is a member of SupportedLanguages + // + Found = FALSE; + if (Iso639Language) { + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } + } else { + Found = !IsLanguageSupported(Language, SupportedLanguages); + } + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + // + // Determine the size of the Unicode String Table by looking for a NULL Language entry + // + NumberOfEntries = 0; + if (*UnicodeStringTable != NULL) { + OldUnicodeStringTable = *UnicodeStringTable; + while (OldUnicodeStringTable->Language != NULL) { + LanguageString = OldUnicodeStringTable->Language; + + while (*LanguageString != 0) { + for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++); + + if (AsciiStrnCmp (Language, LanguageString, Index) == 0) { + return EFI_ALREADY_STARTED; + } + LanguageString += Index; + for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++); + } + OldUnicodeStringTable++; + NumberOfEntries++; + } + } + + // + // Allocate space for a new Unicode String Table. It must hold the current number of + // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table + // marker + // + NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE)); + if (NewUnicodeStringTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If the current Unicode String Table contains any entries, then copy them to the + // newly allocated Unicode String Table. + // + if (*UnicodeStringTable != NULL) { + CopyMem ( + NewUnicodeStringTable, + *UnicodeStringTable, + NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE) + ); + } + + // + // Allocate space for a copy of the Language specifier + // + NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language); + if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) { + FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Compute the length of the Unicode String + // + for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++); + + // + // Allocate space for a copy of the Unicode String + // + NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (StrSize (UnicodeString), UnicodeString); + if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) { + FreePool (NewUnicodeStringTable[NumberOfEntries].Language); + FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Mark the end of the Unicode String Table + // + NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL; + NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL; + + // + // Free the old Unicode String Table + // + if (*UnicodeStringTable != NULL) { + FreePool (*UnicodeStringTable); + } + + // + // Point UnicodeStringTable at the newly allocated Unicode String Table + // + *UnicodeStringTable = NewUnicodeStringTable; + + return EFI_SUCCESS; +} + +/** + This function frees the table of Unicode strings in UnicodeStringTable. + + If UnicodeStringTable is NULL, then EFI_SUCCESS is returned. + Otherwise, each language code, and each Unicode string in the Unicode string + table are freed, and EFI_SUCCESS is returned. + + @param UnicodeStringTable A pointer to the table of Unicode strings. + + @retval EFI_SUCCESS The Unicode string table was freed. + +**/ +EFI_STATUS +EFIAPI +FreeUnicodeStringTable ( + IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable + ) +{ + UINTN Index; + + // + // If the Unicode String Table is NULL, then it is already freed + // + if (UnicodeStringTable == NULL) { + return EFI_SUCCESS; + } + + // + // Loop through the Unicode String Table until we reach the end of table marker + // + for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) { + + // + // Free the Language string from the Unicode String Table + // + FreePool (UnicodeStringTable[Index].Language); + + // + // Free the Unicode String from the Unicode String Table + // + if (UnicodeStringTable[Index].UnicodeString != NULL) { + FreePool (UnicodeStringTable[Index].UnicodeString); + } + } + + // + // Free the Unicode String Table itself + // + FreePool (UnicodeStringTable); + + return EFI_SUCCESS; +} + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function will be deprecated for security reason. + + Returns a pointer to an allocated buffer that contains the contents of a + variable retrieved through the UEFI Runtime Service GetVariable(). The + returned buffer is allocated using AllocatePool(). The caller is responsible + for freeing this buffer with FreePool(). + + If Name is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param[in] Name The pointer to a Null-terminated Unicode string. + @param[in] Guid The pointer to an EFI_GUID structure + + @retval NULL The variable could not be retrieved. + @retval NULL There are not enough resources available for the variable contents. + @retval Other A pointer to allocated buffer containing the variable contents. + +**/ +VOID * +EFIAPI +GetVariable ( + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid + ) +{ + EFI_STATUS Status; + UINTN Size; + VOID *Value; + + ASSERT (Name != NULL); + ASSERT (Guid != NULL); + + // + // Try to get the variable size. + // + Value = NULL; + Size = 0; + Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value); + if (Status != EFI_BUFFER_TOO_SMALL) { + return NULL; + } + + // + // Allocate buffer to get the variable. + // + Value = AllocatePool (Size); + if (Value == NULL) { + return NULL; + } + + // + // Get the variable data. + // + Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value); + if (EFI_ERROR (Status)) { + FreePool(Value); + return NULL; + } + + return Value; +} + +/** + [ATTENTION] This function will be deprecated for security reason. + + Returns a pointer to an allocated buffer that contains the contents of a + variable retrieved through the UEFI Runtime Service GetVariable(). This + function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables. + The returned buffer is allocated using AllocatePool(). The caller is + responsible for freeing this buffer with FreePool(). + + If Name is NULL, then ASSERT(). + + @param[in] Name The pointer to a Null-terminated Unicode string. + + @retval NULL The variable could not be retrieved. + @retval NULL There are not enough resources available for the variable contents. + @retval Other A pointer to allocated buffer containing the variable contents. + +**/ +VOID * +EFIAPI +GetEfiGlobalVariable ( + IN CONST CHAR16 *Name + ) +{ + return GetVariable (Name, &gEfiGlobalVariableGuid); +} +#endif + +/** + Returns the status whether get the variable success. The function retrieves + variable through the UEFI Runtime Service GetVariable(). The + returned buffer is allocated using AllocatePool(). The caller is responsible + for freeing this buffer with FreePool(). + + If Name is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Name The pointer to a Null-terminated Unicode string. + @param[in] Guid The pointer to an EFI_GUID structure + @param[out] Value The buffer point saved the variable info. + @param[out] Size The buffer size of the variable. + + @return EFI_OUT_OF_RESOURCES Allocate buffer failed. + @return EFI_SUCCESS Find the specified variable. + @return Others Errors Return errors from call to gRT->GetVariable. + +**/ +EFI_STATUS +EFIAPI +GetVariable2 ( + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid, + OUT VOID **Value, + OUT UINTN *Size OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + ASSERT (Name != NULL && Guid != NULL && Value != NULL); + + // + // Try to get the variable size. + // + BufferSize = 0; + *Value = NULL; + if (Size != NULL) { + *Size = 0; + } + + Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value); + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + // + // Allocate buffer to get the variable. + // + *Value = AllocatePool (BufferSize); + ASSERT (*Value != NULL); + if (*Value == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get the variable data. + // + Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value); + if (EFI_ERROR (Status)) { + FreePool(*Value); + *Value = NULL; + } + + if (Size != NULL) { + *Size = BufferSize; + } + + return Status; +} + +/** Return the attributes of the variable. + + Returns the status whether get the variable success. The function retrieves + variable through the UEFI Runtime Service GetVariable(). The + returned buffer is allocated using AllocatePool(). The caller is responsible + for freeing this buffer with FreePool(). The attributes are returned if + the caller provides a valid Attribute parameter. + + If Name is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Name The pointer to a Null-terminated Unicode string. + @param[in] Guid The pointer to an EFI_GUID structure + @param[out] Value The buffer point saved the variable info. + @param[out] Size The buffer size of the variable. + @param[out] Attr The pointer to the variable attributes as found in var store + + @retval EFI_OUT_OF_RESOURCES Allocate buffer failed. + @retval EFI_SUCCESS Find the specified variable. + @retval Others Errors Return errors from call to gRT->GetVariable. + +**/ +EFI_STATUS +EFIAPI +GetVariable3( + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid, + OUT VOID **Value, + OUT UINTN *Size OPTIONAL, + OUT UINT32 *Attr OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + ASSERT(Name != NULL && Guid != NULL && Value != NULL); + + // + // Try to get the variable size. + // + BufferSize = 0; + *Value = NULL; + if (Size != NULL) { + *Size = 0; + } + + if (Attr != NULL) { + *Attr = 0; + } + + Status = gRT->GetVariable((CHAR16 *)Name, (EFI_GUID *)Guid, Attr, &BufferSize, *Value); + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + // + // Allocate buffer to get the variable. + // + *Value = AllocatePool(BufferSize); + ASSERT(*Value != NULL); + if (*Value == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get the variable data. + // + Status = gRT->GetVariable((CHAR16 *)Name, (EFI_GUID *)Guid, Attr, &BufferSize, *Value); + if (EFI_ERROR(Status)) { + FreePool(*Value); + *Value = NULL; + } + + if (Size != NULL) { + *Size = BufferSize; + } + + return Status; +} + +/** + Returns a pointer to an allocated buffer that contains the contents of a + variable retrieved through the UEFI Runtime Service GetVariable(). This + function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables. + The returned buffer is allocated using AllocatePool(). The caller is + responsible for freeing this buffer with FreePool(). + + If Name is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Name The pointer to a Null-terminated Unicode string. + @param[out] Value The buffer point saved the variable info. + @param[out] Size The buffer size of the variable. + + @return EFI_OUT_OF_RESOURCES Allocate buffer failed. + @return EFI_SUCCESS Find the specified variable. + @return Others Errors Return errors from call to gRT->GetVariable. + +**/ +EFI_STATUS +EFIAPI +GetEfiGlobalVariable2 ( + IN CONST CHAR16 *Name, + OUT VOID **Value, + OUT UINTN *Size OPTIONAL + ) +{ + return GetVariable2 (Name, &gEfiGlobalVariableGuid, Value, Size); +} + +/** + Returns a pointer to an allocated buffer that contains the best matching language + from a set of supported languages. + + This function supports both ISO 639-2 and RFC 4646 language codes, but language + code types may not be mixed in a single call to this function. The language + code returned is allocated using AllocatePool(). The caller is responsible for + freeing the allocated buffer using FreePool(). This function supports a variable + argument list that allows the caller to pass in a prioritized list of language + codes to test against all the language codes in SupportedLanguages. + + If SupportedLanguages is NULL, then ASSERT(). + + @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that + contains a set of language codes in the format + specified by Iso639Language. + @param[in] Iso639Language If not zero, then all language codes are assumed to be + in ISO 639-2 format. If zero, then all language + codes are assumed to be in RFC 4646 language format + @param[in] ... A variable argument list that contains pointers to + Null-terminated ASCII strings that contain one or more + language codes in the format specified by Iso639Language. + The first language code from each of these language + code lists is used to determine if it is an exact or + close match to any of the language codes in + SupportedLanguages. Close matches only apply to RFC 4646 + language codes, and the matching algorithm from RFC 4647 + is used to determine if a close match is present. If + an exact or close match is found, then the matching + language code from SupportedLanguages is returned. If + no matches are found, then the next variable argument + parameter is evaluated. The variable argument list + is terminated by a NULL. + + @retval NULL The best matching language could not be found in SupportedLanguages. + @retval NULL There are not enough resources available to return the best matching + language. + @retval Other A pointer to a Null-terminated ASCII string that is the best matching + language in SupportedLanguages. + +**/ +CHAR8 * +EFIAPI +GetBestLanguage ( + IN CONST CHAR8 *SupportedLanguages, + IN UINTN Iso639Language, + ... + ) +{ + VA_LIST Args; + CHAR8 *Language; + UINTN CompareLength; + UINTN LanguageLength; + CONST CHAR8 *Supported; + CHAR8 *BestLanguage; + + ASSERT (SupportedLanguages != NULL); + + VA_START (Args, Iso639Language); + while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) { + // + // Default to ISO 639-2 mode + // + CompareLength = 3; + LanguageLength = MIN (3, AsciiStrLen (Language)); + + // + // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language + // + if (Iso639Language == 0) { + for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++); + } + + // + // Trim back the length of Language used until it is empty + // + while (LanguageLength > 0) { + // + // Loop through all language codes in SupportedLanguages + // + for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) { + // + // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages + // + if (Iso639Language == 0) { + // + // Skip ';' characters in Supported + // + for (; *Supported != '\0' && *Supported == ';'; Supported++); + // + // Determine the length of the next language code in Supported + // + for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++); + // + // If Language is longer than the Supported, then skip to the next language + // + if (LanguageLength > CompareLength) { + continue; + } + } + // + // See if the first LanguageLength characters in Supported match Language + // + if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) { + VA_END (Args); + // + // Allocate, copy, and return the best matching language code from SupportedLanguages + // + BestLanguage = AllocateZeroPool (CompareLength + 1); + if (BestLanguage == NULL) { + return NULL; + } + return CopyMem (BestLanguage, Supported, CompareLength); + } + } + + if (Iso639Language != 0) { + // + // If ISO 639 mode, then each language can only be tested once + // + LanguageLength = 0; + } else { + // + // If RFC 4646 mode, then trim Language from the right to the next '-' character + // + for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--); + } + } + } + VA_END (Args); + + // + // No matches were found + // + return NULL; +} + +/** + Returns an array of protocol instance that matches the given protocol. + + @param[in] Protocol Provides the protocol to search for. + @param[out] NoProtocols The number of protocols returned in Buffer. + @param[out] Buffer A pointer to the buffer to return the requested + array of protocol instances that match Protocol. + The returned buffer is allocated using + EFI_BOOT_SERVICES.AllocatePool(). The caller is + responsible for freeing this buffer with + EFI_BOOT_SERVICES.FreePool(). + + @retval EFI_SUCCESS The array of protocols was returned in Buffer, + and the number of protocols in Buffer was + returned in NoProtocols. + @retval EFI_NOT_FOUND No protocols found. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + matching results. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER NoProtocols is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + +**/ +EFI_STATUS +EFIAPI +EfiLocateProtocolBuffer ( + IN EFI_GUID *Protocol, + OUT UINTN *NoProtocols, + OUT VOID ***Buffer + ) +{ + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + // + // Check input parameters + // + if (Protocol == NULL || NoProtocols == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialze output parameters + // + *NoProtocols = 0; + *Buffer = NULL; + + // + // Retrieve the array of handles that support Protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Protocol, + NULL, + &NoHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate array of protocol instances + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + NoHandles * sizeof (VOID *), + (VOID **)Buffer + ); + if (EFI_ERROR (Status)) { + // + // Free the handle buffer + // + gBS->FreePool (HandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + ZeroMem (*Buffer, NoHandles * sizeof (VOID *)); + + // + // Lookup Protocol on each handle in HandleBuffer to fill in the array of + // protocol instances. Handle case where protocol instance was present when + // LocateHandleBuffer() was called, but is not present when HandleProtocol() + // is called. + // + for (Index = 0, *NoProtocols = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + Protocol, + &((*Buffer)[*NoProtocols]) + ); + if (!EFI_ERROR (Status)) { + (*NoProtocols)++; + } + } + + // + // Free the handle buffer + // + gBS->FreePool (HandleBuffer); + + // + // Make sure at least one protocol instance was found + // + if (*NoProtocols == 0) { + gBS->FreePool (*Buffer); + *Buffer = NULL; + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Open or create a file or directory, possibly creating the chain of + directories leading up to the directory. + + EfiOpenFileByDevicePath() first locates EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on + FilePath, and opens the root directory of that filesystem with + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume(). + + On the remaining device path, the longest initial sequence of + FILEPATH_DEVICE_PATH nodes is node-wise traversed with + EFI_FILE_PROTOCOL.Open(). + + (As a consequence, if OpenMode includes EFI_FILE_MODE_CREATE, and Attributes + includes EFI_FILE_DIRECTORY, and each FILEPATH_DEVICE_PATH specifies a single + pathname component, then EfiOpenFileByDevicePath() ensures that the specified + series of subdirectories exist on return.) + + The EFI_FILE_PROTOCOL identified by the last FILEPATH_DEVICE_PATH node is + output to the caller; intermediate EFI_FILE_PROTOCOL instances are closed. If + there are no FILEPATH_DEVICE_PATH nodes past the node that identifies the + filesystem, then the EFI_FILE_PROTOCOL of the root directory of the + filesystem is output to the caller. If a device path node that is different + from FILEPATH_DEVICE_PATH is encountered relative to the filesystem, the + traversal is stopped with an error, and a NULL EFI_FILE_PROTOCOL is output. + + @param[in,out] FilePath On input, the device path to the file or directory + to open or create. The caller is responsible for + ensuring that the device path pointed-to by FilePath + is well-formed. On output, FilePath points one past + the last node in the original device path that has + been successfully processed. FilePath is set on + output even if EfiOpenFileByDevicePath() returns an + error. + + @param[out] File On error, File is set to NULL. On success, File is + set to the EFI_FILE_PROTOCOL of the root directory + of the filesystem, if there are no + FILEPATH_DEVICE_PATH nodes in FilePath; otherwise, + File is set to the EFI_FILE_PROTOCOL identified by + the last node in FilePath. + + @param[in] OpenMode The OpenMode parameter to pass to + EFI_FILE_PROTOCOL.Open(). + + @param[in] Attributes The Attributes parameter to pass to + EFI_FILE_PROTOCOL.Open(). + + @retval EFI_SUCCESS The file or directory has been opened or + created. + + @retval EFI_INVALID_PARAMETER FilePath is NULL; or File is NULL; or FilePath + contains a device path node, past the node + that identifies + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, that is not a + FILEPATH_DEVICE_PATH node. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + + @return Error codes propagated from the + LocateDevicePath() and OpenProtocol() boot + services, and from the + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume() + and EFI_FILE_PROTOCOL.Open() member functions. +**/ +EFI_STATUS +EFIAPI +EfiOpenFileByDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_FILE_PROTOCOL **File, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_HANDLE FileSystemHandle; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; + EFI_FILE_PROTOCOL *LastFile; + FILEPATH_DEVICE_PATH *FilePathNode; + CHAR16 *AlignedPathName; + CHAR16 *PathName; + EFI_FILE_PROTOCOL *NextFile; + + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + *File = NULL; + + if (FilePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Look up the filesystem. + // + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + FilePath, + &FileSystemHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol ( + FileSystemHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&FileSystem, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the root directory of the filesystem. After this operation succeeds, + // we have to release LastFile on error. + // + Status = FileSystem->OpenVolume (FileSystem, &LastFile); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Traverse the device path nodes relative to the filesystem. + // + while (!IsDevicePathEnd (*FilePath)) { + if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP) { + Status = EFI_INVALID_PARAMETER; + goto CloseLastFile; + } + FilePathNode = (FILEPATH_DEVICE_PATH *)*FilePath; + + // + // FilePathNode->PathName may be unaligned, and the UEFI specification + // requires pointers that are passed to protocol member functions to be + // aligned. Create an aligned copy of the pathname if necessary. + // + if ((UINTN)FilePathNode->PathName % sizeof *FilePathNode->PathName == 0) { + AlignedPathName = NULL; + PathName = FilePathNode->PathName; + } else { + AlignedPathName = AllocateCopyPool ( + (DevicePathNodeLength (FilePathNode) - + SIZE_OF_FILEPATH_DEVICE_PATH), + FilePathNode->PathName + ); + if (AlignedPathName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CloseLastFile; + } + PathName = AlignedPathName; + } + + // + // Open or create the file corresponding to the next pathname fragment. + // + Status = LastFile->Open ( + LastFile, + &NextFile, + PathName, + OpenMode, + Attributes + ); + + // + // Release any AlignedPathName on both error and success paths; PathName is + // no longer needed. + // + if (AlignedPathName != NULL) { + FreePool (AlignedPathName); + } + if (EFI_ERROR (Status)) { + goto CloseLastFile; + } + + // + // Advance to the next device path node. + // + LastFile->Close (LastFile); + LastFile = NextFile; + *FilePath = NextDevicePathNode (FilePathNode); + } + + *File = LastFile; + return EFI_SUCCESS; + +CloseLastFile: + LastFile->Close (LastFile); + + // + // We are on the error path; we must have set an error Status for returning + // to the caller. + // + ASSERT (EFI_ERROR (Status)); + return Status; +} diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiLib.inf b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.inf new file mode 100644 index 000000000..01ed92092 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.inf @@ -0,0 +1,88 @@ +## @file +# Instance of UEFI Library. +# +# The UEFI Library provides functions and macros that simplify the development of +# UEFI Drivers and UEFI Applications. These functions and macros help manage EFI +# events, build simple locks utilizing EFI Task Priority Levels (TPLs), install +# EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, +# and print messages on the console output and standard error devices. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiLib + MODULE_UNI_FILE = UefiLib.uni + FILE_GUID = 3a004ba5-efe0-4a61-9f1a-267a46ae5ba9 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + CONSTRUCTOR = UefiLibConstructor + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiLibPrint.c + UefiNotTiano.c + UefiDriverModel.c + Console.c + UefiLib.c + UefiLibInternal.h + Acpi.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + PrintLib + PcdLib + MemoryAllocationLib + DebugLib + BaseMemoryLib + BaseLib + UefiBootServicesTableLib + DevicePathLib + UefiRuntimeServicesTableLib + +[Guids] + gEfiEventReadyToBootGuid ## SOMETIMES_CONSUMES ## Event + gEfiEventLegacyBootGuid ## SOMETIMES_CONSUMES ## Event + gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## Variable + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable + +[Protocols] + gEfiDriverBindingProtocolGuid ## SOMETIMES_PRODUCES + gEfiSimpleTextOutProtocolGuid ## SOMETIMES_CONSUMES + gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiFontProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiUgaDrawProtocolGuid | gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## SOMETIMES_CONSUMES # Consumes if gEfiGraphicsOutputProtocolGuid uninstalled + gEfiComponentNameProtocolGuid | NOT gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiComponentName2ProtocolGuid | NOT gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiDriverConfigurationProtocolGuid ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiDriverConfiguration2ProtocolGuid ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiDriverDiagnosticsProtocolGuid | NOT gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiDriverDiagnostics2ProtocolGuid| NOT gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable ## SOMETIMES_PRODUCES # User chooses to produce it + + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize ## SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiLib.uni b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.uni new file mode 100644 index 000000000..225958429 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiLib.uni @@ -0,0 +1,20 @@ +// /** @file +// Instance of UEFI Library. +// +// The UEFI Library provides functions and macros that simplify the development of +// UEFI Drivers and UEFI Applications. These functions and macros help manage EFI +// events, build simple locks utilizing EFI Task Priority Levels (TPLs), install +// EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, +// and print messages on the console output and standard error devices. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of UEFI Library" + +#string STR_MODULE_DESCRIPTION #language en-US "The UEFI Library provides functions and macros that simplify the development of UEFI Drivers and UEFI Applications. These functions and macros help manage EFI events, build simple locks utilizing EFI Task Priority Levels (TPLs), install EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, and print messages on the console output and standard error devices." + diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h b/roms/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h new file mode 100644 index 000000000..60b5297c7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h @@ -0,0 +1,39 @@ +/** @file + Internal include file for UefiLib. + + Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __UEFI_LIB_INTERNAL_H_ +#define __UEFI_LIB_INTERNAL_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 + +#endif diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c b/roms/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c new file mode 100644 index 000000000..ae3a94eb0 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c @@ -0,0 +1,816 @@ +/** @file + Mde UEFI library API implementation. + Print to StdErr or ConOut defined in EFI_SYSTEM_TABLE + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiLibInternal.h" + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = { + { 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 } +}; + +/** + Internal function which prints a formatted Unicode string to the console output device + specified by Console + + This function prints a formatted Unicode string to the console output device + specified by Console and returns the number of Unicode characters that printed + to it. If the length of the formatted Unicode string is greater than PcdUefiLibMaxPrintBufferSize, + then only the first PcdUefiLibMaxPrintBufferSize characters are sent to Console. + If Format is NULL, then ASSERT(). + If Format is not aligned on a 16-bit boundary, then ASSERT(). + + @param Format A Null-terminated Unicode format string. + @param Console The output console. + @param Marker A VA_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced + output buffer, not including the Null-terminator. +**/ +UINTN +InternalPrint ( + IN CONST CHAR16 *Format, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + UINTN Return; + CHAR16 *Buffer; + UINTN BufferSize; + + ASSERT (Format != NULL); + ASSERT (((UINTN) Format & BIT0) == 0); + ASSERT (Console != NULL); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + Buffer = (CHAR16 *) AllocatePool(BufferSize); + ASSERT (Buffer != NULL); + + Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker); + + if (Console != NULL && Return > 0) { + // + // To be extra safe make sure Console has been initialized + // + Status = Console->OutputString (Console, Buffer); + if (EFI_ERROR (Status)) { + Return = 0; + } + } + + FreePool (Buffer); + + return Return; +} + +/** + Prints a formatted Unicode string to the console output device specified by + ConOut defined in the EFI_SYSTEM_TABLE. + + This function prints a formatted Unicode string to the console output device + specified by ConOut in EFI_SYSTEM_TABLE and returns the number of Unicode + characters that printed to ConOut. If the length of the formatted Unicode + string is greater than PcdUefiLibMaxPrintBufferSize, then only the first + PcdUefiLibMaxPrintBufferSize characters are sent to ConOut. + If Format is NULL, then ASSERT(). + If Format is not aligned on a 16-bit boundary, then ASSERT(). + If gST->ConOut is NULL, then ASSERT(). + + @param Format A Null-terminated Unicode format string. + @param ... A Variable argument list whose contents are accessed based + on the format string specified by Format. + + @return The number of Unicode characters printed to ConOut. + +**/ +UINTN +EFIAPI +Print ( + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + + VA_START (Marker, Format); + + Return = InternalPrint (Format, gST->ConOut, Marker); + + VA_END (Marker); + + return Return; +} + +/** + Prints a formatted Unicode string to the console output device specified by + StdErr defined in the EFI_SYSTEM_TABLE. + + This function prints a formatted Unicode string to the console output device + specified by StdErr in EFI_SYSTEM_TABLE and returns the number of Unicode + characters that printed to StdErr. If the length of the formatted Unicode + string is greater than PcdUefiLibMaxPrintBufferSize, then only the first + PcdUefiLibMaxPrintBufferSize characters are sent to StdErr. + If Format is NULL, then ASSERT(). + If Format is not aligned on a 16-bit boundary, then ASSERT(). + If gST->StdErr is NULL, then ASSERT(). + + @param Format A Null-terminated Unicode format string. + @param ... Variable argument list whose contents are accessed based + on the format string specified by Format. + + @return The number of Unicode characters printed to StdErr. + +**/ +UINTN +EFIAPI +ErrorPrint ( + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + + VA_START (Marker, Format); + + Return = InternalPrint( Format, gST->StdErr, Marker); + + VA_END (Marker); + + return Return; +} + + +/** + Internal function which prints a formatted ASCII string to the console output device + specified by Console + + This function prints a formatted ASCII string to the console output device + specified by Console and returns the number of ASCII characters that printed + to it. If the length of the formatted ASCII string is greater than PcdUefiLibMaxPrintBufferSize, + then only the first PcdUefiLibMaxPrintBufferSize characters are sent to Console. + + If Format is NULL, then ASSERT(). + + @param Format A Null-terminated ASCII format string. + @param Console The output console. + @param Marker VA_LIST marker for the variable argument list. + + @return The number of Unicode characters in the produced + output buffer not including the Null-terminator. + +**/ +UINTN +AsciiInternalPrint ( + IN CONST CHAR8 *Format, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + UINTN Return; + CHAR16 *Buffer; + UINTN BufferSize; + + ASSERT (Format != NULL); + ASSERT (Console != NULL); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + Buffer = (CHAR16 *) AllocatePool(BufferSize); + ASSERT (Buffer != NULL); + + Return = UnicodeVSPrintAsciiFormat (Buffer, BufferSize, Format, Marker); + + if (Console != NULL) { + // + // To be extra safe make sure Console has been initialized + // + Status = Console->OutputString (Console, Buffer); + if (EFI_ERROR (Status)) { + Return = 0; + } + } + + FreePool (Buffer); + + return Return; +} + +/** + Prints a formatted ASCII string to the console output device specified by + ConOut defined in the EFI_SYSTEM_TABLE. + + This function prints a formatted ASCII string to the console output device + specified by ConOut in EFI_SYSTEM_TABLE and returns the number of ASCII + characters that printed to ConOut. If the length of the formatted ASCII + string is greater than PcdUefiLibMaxPrintBufferSize, then only the first + PcdUefiLibMaxPrintBufferSize characters are sent to ConOut. + If Format is NULL, then ASSERT(). + If gST->ConOut is NULL, then ASSERT(). + + @param Format A Null-terminated ASCII format string. + @param ... Variable argument list whose contents are accessed based + on the format string specified by Format. + + @return The number of ASCII characters printed to ConOut. + +**/ +UINTN +EFIAPI +AsciiPrint ( + IN CONST CHAR8 *Format, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + ASSERT (Format != NULL); + + VA_START (Marker, Format); + + Return = AsciiInternalPrint( Format, gST->ConOut, Marker); + + VA_END (Marker); + + return Return; +} + +/** + Prints a formatted ASCII string to the console output device specified by + StdErr defined in the EFI_SYSTEM_TABLE. + + This function prints a formatted ASCII string to the console output device + specified by StdErr in EFI_SYSTEM_TABLE and returns the number of ASCII + characters that printed to StdErr. If the length of the formatted ASCII + string is greater than PcdUefiLibMaxPrintBufferSize, then only the first + PcdUefiLibMaxPrintBufferSize characters are sent to StdErr. + If Format is NULL, then ASSERT(). + If gST->StdErr is NULL, then ASSERT(). + + @param Format A Null-terminated ASCII format string. + @param ... Variable argument list whose contents are accessed based + on the format string specified by Format. + + @return The number of ASCII characters printed to ConErr. + +**/ +UINTN +EFIAPI +AsciiErrorPrint ( + IN CONST CHAR8 *Format, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + + ASSERT (Format != NULL); + + VA_START (Marker, Format); + + Return = AsciiInternalPrint( Format, gST->StdErr, Marker); + + VA_END (Marker); + + return Return; +} + +/** + Internal function to print a formatted Unicode string to a graphics console device specified by + ConsoleOutputHandle defined in the EFI_SYSTEM_TABLE at the given (X,Y) coordinates. + + This function prints a formatted Unicode string to the graphics console device + specified by ConsoleOutputHandle in EFI_SYSTEM_TABLE and returns the number of + Unicode characters printed. The EFI_HII_FONT_PROTOCOL is used to convert the + string to a bitmap using the glyphs registered with the + HII database. No wrapping is performed, so any portions of the string the fall + outside the active display region will not be displayed. + + If a graphics console device is not associated with the ConsoleOutputHandle + defined in the EFI_SYSTEM_TABLE then no string is printed, and 0 is returned. + If the EFI_HII_FONT_PROTOCOL is not present in the handle database, then no + string is printed, and 0 is returned. + + @param PointX An X coordinate to print the string. + @param PointY A Y coordinate to print the string. + @param Foreground The foreground color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the foreground color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param Background The background color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the background color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param Buffer A Null-terminated Unicode formatted string. + @param PrintNum The number of Unicode formatted string to be printed. + + @return The number of Unicode Characters printed. Zero means no any character + displayed successfully. + +**/ +UINTN +InternalPrintGraphic ( + IN UINTN PointX, + IN UINTN PointY, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background, + IN CHAR16 *Buffer, + IN UINTN PrintNum + ) +{ + EFI_STATUS Status; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_HII_FONT_PROTOCOL *HiiFont; + EFI_IMAGE_OUTPUT *Blt; + EFI_FONT_DISPLAY_INFO FontInfo; + EFI_HII_ROW_INFO *RowInfoArray; + UINTN RowInfoArraySize; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto; + EFI_HANDLE ConsoleHandle; + UINTN Width; + UINTN Height; + UINTN Delta; + + HorizontalResolution = 0; + VerticalResolution = 0; + Blt = NULL; + RowInfoArray = NULL; + + ConsoleHandle = gST->ConsoleOutHandle; + + ASSERT( ConsoleHandle != NULL); + + Status = gBS->HandleProtocol ( + ConsoleHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput + ); + + UgaDraw = NULL; + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + // + // If no GOP available, try to open UGA Draw protocol if supported. + // + GraphicsOutput = NULL; + + Status = gBS->HandleProtocol ( + ConsoleHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw + ); + } + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = gBS->HandleProtocol ( + ConsoleHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &Sto + ); + + if (EFI_ERROR (Status)) { + goto Error; + } + + if (GraphicsOutput != NULL) { + HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; + VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; + } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate); + } else { + goto Error; + } + + ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0)); + + Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont); + if (EFI_ERROR (Status)) { + goto Error; + } + + Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT)); + ASSERT (Blt != NULL); + + Blt->Width = (UINT16) (HorizontalResolution); + Blt->Height = (UINT16) (VerticalResolution); + + ZeroMem (&FontInfo, sizeof (EFI_FONT_DISPLAY_INFO)); + + if (Foreground != NULL) { + CopyMem (&FontInfo.ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + } else { + CopyMem ( + &FontInfo.ForegroundColor, + &mEfiColors[Sto->Mode->Attribute & 0x0f], + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } + if (Background != NULL) { + CopyMem (&FontInfo.BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + } else { + CopyMem ( + &FontInfo.BackgroundColor, + &mEfiColors[Sto->Mode->Attribute >> 4], + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } + + if (GraphicsOutput != NULL) { + Blt->Image.Screen = GraphicsOutput; + + Status = HiiFont->StringToImage ( + HiiFont, + EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_OUT_FLAG_CLIP | + EFI_HII_OUT_FLAG_CLIP_CLEAN_X | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y | + EFI_HII_IGNORE_LINE_BREAK | EFI_HII_DIRECT_TO_SCREEN, + Buffer, + &FontInfo, + &Blt, + PointX, + PointY, + &RowInfoArray, + &RowInfoArraySize, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + ASSERT (UgaDraw!= NULL); + + // + // Ensure Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow. + // + if (Blt->Width > DivU64x32 (MAX_UINTN, Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { + goto Error; + } + + Blt->Image.Bitmap = AllocateZeroPool ((UINT32) Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + ASSERT (Blt->Image.Bitmap != NULL); + + // + // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform, + // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw. + // + Status = HiiFont->StringToImage ( + HiiFont, + EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_OUT_FLAG_CLIP | + EFI_HII_OUT_FLAG_CLIP_CLEAN_X | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y | + EFI_HII_IGNORE_LINE_BREAK, + Buffer, + &FontInfo, + &Blt, + PointX, + PointY, + &RowInfoArray, + &RowInfoArraySize, + NULL + ); + + if (!EFI_ERROR (Status)) { + ASSERT (RowInfoArray != NULL); + // + // Explicit Line break characters are ignored, so the updated parameter RowInfoArraySize by StringToImage will + // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure. + // + ASSERT (RowInfoArraySize <= 1); + + if (RowInfoArraySize != 0) { + Width = RowInfoArray[0].LineWidth; + Height = RowInfoArray[0].LineHeight; + Delta = Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } else { + Width = 0; + Height = 0; + Delta = 0; + } + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) Blt->Image.Bitmap, + EfiUgaBltBufferToVideo, + PointX, + PointY, + PointX, + PointY, + Width, + Height, + Delta + ); + } else { + goto Error; + } + FreePool (Blt->Image.Bitmap); + } else { + goto Error; + } + // + // Calculate the number of actual printed characters + // + if (RowInfoArraySize != 0) { + PrintNum = RowInfoArray[0].EndIndex - RowInfoArray[0].StartIndex + 1; + } else { + PrintNum = 0; + } + + FreePool (RowInfoArray); + FreePool (Blt); + return PrintNum; + +Error: + if (Blt != NULL) { + FreePool (Blt); + } + return 0; +} + +/** + Prints a formatted Unicode string to a graphics console device specified by + ConsoleOutputHandle defined in the EFI_SYSTEM_TABLE at the given (X,Y) coordinates. + + This function prints a formatted Unicode string to the graphics console device + specified by ConsoleOutputHandle in EFI_SYSTEM_TABLE and returns the number of + Unicode characters displayed, not including partial characters that may be clipped + by the right edge of the display. If the length of the formatted Unicode string is + greater than PcdUefiLibMaxPrintBufferSize, then at most the first + PcdUefiLibMaxPrintBufferSize characters are printed.The EFI_HII_FONT_PROTOCOL + StringToImage() service is used to convert the string to a bitmap using the glyphs + registered with the HII database. No wrapping is performed, so any portions of the + string the fall outside the active display region will not be displayed. Please see + Section 27.2.6 of the UEFI Specification for a description of the supported string + format including the set of control codes supported by the StringToImage() service. + + If a graphics console device is not associated with the ConsoleOutputHandle + defined in the EFI_SYSTEM_TABLE then no string is printed, and 0 is returned. + If the EFI_HII_FONT_PROTOCOL is not present in the handle database, then no + string is printed, and 0 is returned. + If Format is NULL, then ASSERT(). + If Format is not aligned on a 16-bit boundary, then ASSERT(). + If gST->ConsoleOutputHandle is NULL, then ASSERT(). + + @param PointX An X coordinate to print the string. + @param PointY A Y coordinate to print the string. + @param ForeGround The foreground color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the foreground color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param BackGround The background color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the background color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param Format A Null-terminated Unicode format string. See Print Library + for the supported format string syntax. + @param ... A Variable argument list whose contents are accessed based on + the format string specified by Format. + + @return The number of Unicode characters printed. + +**/ +UINTN +EFIAPI +PrintXY ( + IN UINTN PointX, + IN UINTN PointY, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + CHAR16 *Buffer; + UINTN BufferSize; + UINTN PrintNum; + UINTN ReturnNum; + + ASSERT (Format != NULL); + ASSERT (((UINTN) Format & BIT0) == 0); + + VA_START (Marker, Format); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + Buffer = (CHAR16 *) AllocatePool (BufferSize); + ASSERT (Buffer != NULL); + + PrintNum = UnicodeVSPrint (Buffer, BufferSize, Format, Marker); + + VA_END (Marker); + + ReturnNum = InternalPrintGraphic (PointX, PointY, ForeGround, BackGround, Buffer, PrintNum); + + FreePool (Buffer); + + return ReturnNum; +} + +/** + Prints a formatted ASCII string to a graphics console device specified by + ConsoleOutputHandle defined in the EFI_SYSTEM_TABLE at the given (X,Y) coordinates. + + This function prints a formatted ASCII string to the graphics console device + specified by ConsoleOutputHandle in EFI_SYSTEM_TABLE and returns the number of + ASCII characters displayed, not including partial characters that may be clipped + by the right edge of the display. If the length of the formatted ASCII string is + greater than PcdUefiLibMaxPrintBufferSize, then at most the first + PcdUefiLibMaxPrintBufferSize characters are printed.The EFI_HII_FONT_PROTOCOL + StringToImage() service is used to convert the string to a bitmap using the glyphs + registered with the HII database. No wrapping is performed, so any portions of the + string the fall outside the active display region will not be displayed. Please see + Section 27.2.6 of the UEFI Specification for a description of the supported string + format including the set of control codes supported by the StringToImage() service. + + If a graphics console device is not associated with the ConsoleOutputHandle + defined in the EFI_SYSTEM_TABLE then no string is printed, and 0 is returned. + If the EFI_HII_FONT_PROTOCOL is not present in the handle database, then no + string is printed, and 0 is returned. + If Format is NULL, then ASSERT(). + If gST->ConsoleOutputHandle is NULL, then ASSERT(). + + @param PointX An X coordinate to print the string. + @param PointY A Y coordinate to print the string. + @param ForeGround The foreground color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the foreground color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param BackGround The background color of the string being printed. This is + an optional parameter that may be NULL. If it is NULL, + then the background color of the current ConOut device + in the EFI_SYSTEM_TABLE is used. + @param Format A Null-terminated ASCII format string. See Print Library + for the supported format string syntax. + @param ... Variable argument list whose contents are accessed based on + the format string specified by Format. + + @return The number of ASCII characters printed. + +**/ +UINTN +EFIAPI +AsciiPrintXY ( + IN UINTN PointX, + IN UINTN PointY, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL + IN CONST CHAR8 *Format, + ... + ) +{ + VA_LIST Marker; + CHAR16 *Buffer; + UINTN BufferSize; + UINTN PrintNum; + UINTN ReturnNum; + + ASSERT (Format != NULL); + + VA_START (Marker, Format); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + Buffer = (CHAR16 *) AllocatePool (BufferSize); + ASSERT (Buffer != NULL); + + PrintNum = UnicodeSPrintAsciiFormat (Buffer, BufferSize, Format, Marker); + + VA_END (Marker); + + ReturnNum = InternalPrintGraphic (PointX, PointY, ForeGround, BackGround, Buffer, PrintNum); + + FreePool (Buffer); + + return ReturnNum; +} + +/** + Appends a formatted Unicode string to a Null-terminated Unicode string + + This function appends a formatted Unicode string to the Null-terminated + Unicode string specified by String. String is optional and may be NULL. + Storage for the formatted Unicode string returned is allocated using + AllocatePool(). The pointer to the appended string is returned. The caller + is responsible for freeing the returned string. + + If String is not NULL and not aligned on a 16-bit boundary, then ASSERT(). + If FormatString is NULL, then ASSERT(). + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] String A Null-terminated Unicode string. + @param[in] FormatString A Null-terminated Unicode format string. + @param[in] Marker VA_LIST marker for the variable argument list. + + @retval NULL There was not enough available memory. + @return Null-terminated Unicode string is that is the formatted + string appended to String. +**/ +CHAR16* +EFIAPI +CatVSPrint ( + IN CHAR16 *String, OPTIONAL + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + UINTN CharactersRequired; + UINTN SizeRequired; + CHAR16 *BufferToReturn; + VA_LIST ExtraMarker; + + VA_COPY (ExtraMarker, Marker); + CharactersRequired = SPrintLength(FormatString, ExtraMarker); + VA_END (ExtraMarker); + + if (String != NULL) { + SizeRequired = StrSize(String) + (CharactersRequired * sizeof(CHAR16)); + } else { + SizeRequired = sizeof(CHAR16) + (CharactersRequired * sizeof(CHAR16)); + } + + BufferToReturn = AllocatePool(SizeRequired); + + if (BufferToReturn == NULL) { + return NULL; + } else { + BufferToReturn[0] = L'\0'; + } + + if (String != NULL) { + StrCpyS(BufferToReturn, SizeRequired / sizeof(CHAR16), String); + } + + UnicodeVSPrint(BufferToReturn + StrLen(BufferToReturn), (CharactersRequired+1) * sizeof(CHAR16), FormatString, Marker); + + ASSERT(StrSize(BufferToReturn)==SizeRequired); + + return (BufferToReturn); +} + +/** + Appends a formatted Unicode string to a Null-terminated Unicode string + + This function appends a formatted Unicode string to the Null-terminated + Unicode string specified by String. String is optional and may be NULL. + Storage for the formatted Unicode string returned is allocated using + AllocatePool(). The pointer to the appended string is returned. The caller + is responsible for freeing the returned string. + + If String is not NULL and not aligned on a 16-bit boundary, then ASSERT(). + If FormatString is NULL, then ASSERT(). + If FormatString is not aligned on a 16-bit boundary, then ASSERT(). + + @param[in] String A Null-terminated Unicode string. + @param[in] FormatString A Null-terminated Unicode format string. + @param[in] ... The variable argument list whose contents are + accessed based on the format string specified by + FormatString. + + @retval NULL There was not enough available memory. + @return Null-terminated Unicode string is that is the formatted + string appended to String. +**/ +CHAR16 * +EFIAPI +CatSPrint ( + IN CHAR16 *String, OPTIONAL + IN CONST CHAR16 *FormatString, + ... + ) +{ + VA_LIST Marker; + CHAR16 *NewString; + + VA_START (Marker, FormatString); + NewString = CatVSPrint(String, FormatString, Marker); + VA_END (Marker); + return NewString; +} + diff --git a/roms/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c b/roms/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c new file mode 100644 index 000000000..5e32f4abf --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c @@ -0,0 +1,330 @@ +/** @file + Library functions that abstract areas of conflict between framework and UEFI 2.0. + + Help Port Framework code that has conflicts with UEFI 2.0 by hiding the + old conflicts with library functions and supporting implementations of the old + (EDK/EFI 1.10) and new (EDK II/UEFI 2.0) way. This module is a DXE driver as + it contains DXE enum extensions for EFI event services. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include "UefiLibInternal.h" + +/** + Creates an EFI event in the Legacy Boot Event Group. + + Prior to UEFI 2.0 this was done via a non blessed UEFI extensions and this library + abstracts the implementation mechanism of this event from the caller. This function + abstracts the creation of the Legacy Boot Event. The Framework moved from a proprietary + to UEFI 2.0 based mechanism. This library abstracts the caller from how this event + is created to prevent to code form having to change with the version of the + specification supported. + If LegacyBootEvent is NULL, then ASSERT(). + + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventLegacyBoot ( + OUT EFI_EVENT *LegacyBootEvent + ) +{ + return EfiCreateEventLegacyBootEx ( + TPL_CALLBACK, + EfiEventEmptyFunction, + NULL, + LegacyBootEvent + ); +} + +/** + Create an EFI event in the Legacy Boot Event Group and allows + the caller to specify a notification function. + + This function abstracts the creation of the Legacy Boot Event. + The Framework moved from a proprietary to UEFI 2.0 based mechanism. + This library abstracts the caller from how this event is created to prevent + to code form having to change with the version of the specification supported. + If LegacyBootEvent is NULL, then ASSERT(). + + @param NotifyTpl The task priority level of the event. + @param NotifyFunction The notification function to call when the event is signaled. + @param NotifyContext The content to pass to NotifyFunction when the event is signaled. + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventLegacyBootEx ( + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN VOID *NotifyContext, OPTIONAL + OUT EFI_EVENT *LegacyBootEvent + ) +{ + EFI_STATUS Status; + EFI_EVENT_NOTIFY WorkerNotifyFunction; + + ASSERT (LegacyBootEvent != NULL); + + if (gST->Hdr.Revision < EFI_2_00_SYSTEM_TABLE_REVISION) { + DEBUG ((EFI_D_ERROR, "EFI1.1 can't support LegacyBootEvent!")); + ASSERT (FALSE); + + return EFI_UNSUPPORTED; + } else { + // + // For UEFI 2.0 and the future use an Event Group + // + if (NotifyFunction == NULL) { + // + // CreateEventEx will check NotifyFunction is NULL or not and return error. + // Use dummy routine for the case NotifyFunction is NULL. + // + WorkerNotifyFunction = EfiEventEmptyFunction; + } else { + WorkerNotifyFunction = NotifyFunction; + } + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + NotifyTpl, + WorkerNotifyFunction, + NotifyContext, + &gEfiEventLegacyBootGuid, + LegacyBootEvent + ); + } + + return Status; +} + +/** + Create an EFI event in the Ready To Boot Event Group. + + Prior to UEFI 2.0 this was done via a non-standard UEFI extension, and this library + abstracts the implementation mechanism of this event from the caller. + This function abstracts the creation of the Ready to Boot Event. The Framework + moved from a proprietary to UEFI 2.0-based mechanism. This library abstracts + the caller from how this event is created to prevent the code form having to + change with the version of the specification supported. + If ReadyToBootEvent is NULL, then ASSERT(). + + @param ReadyToBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventReadyToBoot ( + OUT EFI_EVENT *ReadyToBootEvent + ) +{ + return EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + EfiEventEmptyFunction, + NULL, + ReadyToBootEvent + ); +} + +/** + Create an EFI event in the Ready To Boot Event Group and allows + the caller to specify a notification function. + + This function abstracts the creation of the Ready to Boot Event. + The Framework moved from a proprietary to UEFI 2.0 based mechanism. + This library abstracts the caller from how this event is created to prevent + to code form having to change with the version of the specification supported. + If ReadyToBootEvent is NULL, then ASSERT(). + + @param NotifyTpl The task priority level of the event. + @param NotifyFunction The notification function to call when the event is signaled. + @param NotifyContext The content to pass to NotifyFunction when the event is signaled. + @param ReadyToBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventReadyToBootEx ( + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN VOID *NotifyContext, OPTIONAL + OUT EFI_EVENT *ReadyToBootEvent + ) +{ + EFI_STATUS Status; + EFI_EVENT_NOTIFY WorkerNotifyFunction; + + ASSERT (ReadyToBootEvent != NULL); + + if (gST->Hdr.Revision < EFI_2_00_SYSTEM_TABLE_REVISION) { + DEBUG ((EFI_D_ERROR, "EFI1.1 can't support ReadyToBootEvent!")); + ASSERT (FALSE); + + return EFI_UNSUPPORTED; + } else { + // + // For UEFI 2.0 and the future use an Event Group + // + if (NotifyFunction == NULL) { + // + // CreateEventEx will check NotifyFunction is NULL or not and return error. + // Use dummy routine for the case NotifyFunction is NULL. + // + WorkerNotifyFunction = EfiEventEmptyFunction; + } else { + WorkerNotifyFunction = NotifyFunction; + } + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + NotifyTpl, + WorkerNotifyFunction, + NotifyContext, + &gEfiEventReadyToBootGuid, + ReadyToBootEvent + ); + } + + return Status; +} + + +/** + Create, Signal, and Close the Ready to Boot event using EfiSignalEventReadyToBoot(). + + This function abstracts the signaling of the Ready to Boot Event. The Framework moved + from a proprietary to UEFI 2.0 based mechanism. This library abstracts the caller + from how this event is created to prevent to code form having to change with the + version of the specification supported. + +**/ +VOID +EFIAPI +EfiSignalEventReadyToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ReadyToBootEvent; + + Status = EfiCreateEventReadyToBoot (&ReadyToBootEvent); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (ReadyToBootEvent); + gBS->CloseEvent (ReadyToBootEvent); + } +} + +/** + Create, Signal, and Close the Ready to Boot event using EfiSignalEventLegacyBoot(). + + This function abstracts the signaling of the Legacy Boot Event. The Framework moved from + a proprietary to UEFI 2.0 based mechanism. This library abstracts the caller from how + this event is created to prevent to code form having to change with the version of the + specification supported. + +**/ +VOID +EFIAPI +EfiSignalEventLegacyBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT LegacyBootEvent; + + Status = EfiCreateEventLegacyBoot (&LegacyBootEvent); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (LegacyBootEvent); + gBS->CloseEvent (LegacyBootEvent); + } +} + + +/** + Check to see if the Firmware Volume (FV) Media Device Path is valid + + The Framework FwVol Device Path changed to conform to the UEFI 2.0 specification. + This library function abstracts validating a device path node. + Check the MEDIA_FW_VOL_FILEPATH_DEVICE_PATH data structure to see if it's valid. + If it is valid, then return the GUID file name from the device path node. Otherwise, + return NULL. This device path changed in the DXE CIS version 0.92 in a non back ward + compatible way to not conflict with the UEFI 2.0 specification. This function abstracts + the differences from the caller. + If FvDevicePathNode is NULL, then ASSERT(). + + @param FvDevicePathNode The pointer to FV device path to check. + + @retval NULL FvDevicePathNode is not valid. + @retval Other FvDevicePathNode is valid and pointer to NameGuid was returned. + +**/ +EFI_GUID * +EFIAPI +EfiGetNameGuidFromFwVolDevicePathNode ( + IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode + ) +{ + ASSERT (FvDevicePathNode != NULL); + + if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH && + DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_PIWG_FW_FILE_DP) { + return (EFI_GUID *) &FvDevicePathNode->FvFileName; + } + + return NULL; +} + + +/** + Initialize a Firmware Volume (FV) Media Device Path node. + + The Framework FwVol Device Path changed to conform to the UEFI 2.0 specification. + This library function abstracts initializing a device path node. + Initialize the MEDIA_FW_VOL_FILEPATH_DEVICE_PATH data structure. This device + path changed in the DXE CIS version 0.92 in a non back ward compatible way to + not conflict with the UEFI 2.0 specification. This function abstracts the + differences from the caller. + If FvDevicePathNode is NULL, then ASSERT(). + If NameGuid is NULL, then ASSERT(). + + @param FvDevicePathNode The pointer to a FV device path node to initialize + @param NameGuid FV file name to use in FvDevicePathNode + +**/ +VOID +EFIAPI +EfiInitializeFwVolDevicepathNode ( + IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode, + IN CONST EFI_GUID *NameGuid + ) +{ + ASSERT (FvDevicePathNode != NULL); + ASSERT (NameGuid != NULL); + + // + // Use the new Device path that does not conflict with the UEFI + // + FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH; + FvDevicePathNode->Header.SubType = MEDIA_PIWG_FW_FILE_DP; + SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)); + + CopyGuid (&FvDevicePathNode->FvFileName, NameGuid); +} + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 000000000..554b6a7e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,815 @@ +/** @file + Support routines for memory allocation routines based + on boot services for Dxe phase drivers. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include +#include +#include + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiBootServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiReservedMemoryType, Pages); +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment + specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then + NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiBootServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiReservedMemoryType, AllocationSize); +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer + with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid + buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request, + then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiBootServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer); +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = gBS->FreePool (Buffer); + ASSERT_EFI_ERROR (Status); +} + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf new file mode 100644 index 000000000..4d14a157f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf @@ -0,0 +1,37 @@ +## @file +# Instance of Memory Allocation Library using EFI Boot Services. +# +# Memory Allocation Library that uses EFI Boot Services to allocate +# and free memory. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiMemoryAllocationLib + MODULE_UNI_FILE = UefiMemoryAllocationLib.uni + FILE_GUID = 4674739d-3195-4fb2-8094-ac1d22d00194 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryAllocationLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + MemoryAllocationLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + UefiBootServicesTableLib + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni new file mode 100644 index 000000000..034d352f9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Memory Allocation Library using EFI Boot Services. +// +// Memory Allocation Library that uses EFI Boot Services to allocate +// and free memory. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library using EFI Boot Services" + +#string STR_MODULE_DESCRIPTION #language en-US "This Memory Allocation Library uses EFI Boot Services to allocate and free memory." + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c new file mode 100644 index 000000000..6c539a685 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c @@ -0,0 +1,60 @@ +/** @file + CompareMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Compares the contents of two buffers. + + This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). + If Length > 0 and SourceBuffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer to compare. + @param SourceBuffer The pointer to the source buffer to compare. + @param Length The number of bytes to compare. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0 || DestinationBuffer == SourceBuffer) { + return 0; + } + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c new file mode 100644 index 000000000..438abf4e8 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c @@ -0,0 +1,57 @@ +/** @file + CopyMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and returns + DestinationBuffer. The implementation must be reentrant, and it must handle the case + where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return DestinationBuffer; + } + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)DestinationBuffer)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)SourceBuffer)); + + if (DestinationBuffer == SourceBuffer) { + return DestinationBuffer; + } + return InternalMemCopyMem (DestinationBuffer, SourceBuffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 000000000..10be08107 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,48 @@ +/** @file + Implementation of IsZeroBuffer function. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + ASSERT (!(Buffer == NULL && Length > 0)); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + return InternalMemIsZeroBuffer (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c new file mode 100644 index 000000000..983db8c3f --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c @@ -0,0 +1,57 @@ +/** @file + Base Memory Library functions implementation bases on Uefi Boot Service. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function wraps the gBS->CopyMem(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + gBS->CopyMem (Destination, (VOID*)Source, Length); + return Destination; +} + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function wraps the gBS->SetMem(). + + @param Buffer Memory to set. + @param Size The number of bytes to set. + @param Value Value of the set operation. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + gBS->SetMem (Buffer, Size, Value); + return Buffer; +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c new file mode 100644 index 000000000..73ef0d92d --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c @@ -0,0 +1,283 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT16*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT32*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT64*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Length The number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer + @param SourceBuffer The second memory buffer + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + Pointer = (CONST UINT8*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + Pointer = (CONST UINT16*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + Pointer = (CONST UINT32*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + Pointer = (CONST UINT64*)Buffer; + do { + if (*(Pointer++) == Value) { + return --Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + CONST UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < Length; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c new file mode 100644 index 000000000..319487dda --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @file + Implementation of GUID functions. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid to + DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid The pointer to the destination GUID. + @param SourceGuid The pointer to the source GUID. + + @return DestinationGuid. + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs. + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. + If there are any bit differences in the two GUIDs, then FALSE is returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 A pointer to a 128 bit GUID. + @param Guid2 A pointer to a 128 bit GUID. + + @retval TRUE Guid1 and Guid2 are identical. + @retval FALSE Guid1 and Guid2 are not identical. + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + UINT64 LowPartOfGuid1; + UINT64 LowPartOfGuid2; + UINT64 HighPartOfGuid1; + UINT64 HighPartOfGuid2; + + LowPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1); + LowPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2); + HighPartOfGuid1 = ReadUnaligned64 ((CONST UINT64*) Guid1 + 1); + HighPartOfGuid2 = ReadUnaligned64 ((CONST UINT64*) Guid2 + 1); + + return (BOOLEAN) (LowPartOfGuid1 == LowPartOfGuid2 && HighPartOfGuid1 == HighPartOfGuid2); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Guid The value to search for in the target buffer. + + @return A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0); + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + +/** + Checks if the given GUID is a zero GUID. + + This function checks whether the given GUID is a zero GUID. If the GUID is + identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned. + + If Guid is NULL, then ASSERT(). + + @param Guid The pointer to a 128 bit GUID. + + @retval TRUE Guid is a zero GUID. + @retval FALSE Guid is not a zero GUID. + +**/ +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + UINT64 LowPartOfGuid; + UINT64 HighPartOfGuid; + + LowPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid); + HighPartOfGuid = ReadUnaligned64 ((CONST UINT64*) Guid + 1); + + return (BOOLEAN) (LowPartOfGuid == 0 && HighPartOfGuid == 0); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h new file mode 100644 index 000000000..cda2a52d7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h @@ -0,0 +1,243 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEM_LIB_INTERNALS__ +#define __MEM_LIB_INTERNALS__ + +#include + +#include +#include +#include +#include + +/** + Copies a source buffer to a destination buffer, and returns the destination buffer. + + This function wraps the gBS->CopyMem(). + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @return DestinationBuffer. + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ); + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function wraps the gBS->SetMem(). + + @param Buffer Memory to set. + @param Size The number of bytes to set. + @param Value Value of the set operation. + + @return Buffer. + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 16-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 32-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer The pointer to the target buffer to fill. + @param Length The count of 64-bit value to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer The memory to set. + @param Length The number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer The first memory buffer + @param SourceBuffer The second memory buffer + @param Length The length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @return 0 All Length bytes of the two buffers are identical. + @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first + mismatched byte in DestinationBuffer. + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 8-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 16-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 32-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer The pointer to the target buffer to scan. + @param Length The count of 64-bit value to scan. Must be non-zero. + @param Value The value to search for in the target buffer. + + @return The pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ); + +#endif diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 000000000..820131352 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the matching 16-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 16-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 000000000..22c0c79ff --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,60 @@ +/** @file + ScanMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the matching 32-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 32-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 000000000..a617d870a --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,61 @@ +/** @file + ScanMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the matching 64-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a 64-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return NULL; + } + + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return (VOID*)InternalMemScanMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 000000000..f2bf7d6f6 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,93 @@ +/** @file + ScanMem8() and ScanMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the matching 8-bit value + in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for an 8-bit value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return NULL; + } + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a UINTN sized value, and returns a pointer to the matching + UINTN sized value in the target buffer. + + This function searches the target buffer specified by Buffer and Length from the lowest + address to the highest address for a UINTN sized value that matches Value. If a match is found, + then a pointer to the matching byte in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to scan. + @param Length The number of bytes in Buffer to scan. + @param Value The value to search for in the target buffer. + + @return A pointer to the matching byte in the target buffer or NULL otherwise. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return ScanMem64 (Buffer, Length, (UINT64)Value); + } else { + return ScanMem32 (Buffer, Length, (UINT32)Value); + } +} + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c new file mode 100644 index 000000000..5d85a295e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem16() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem16 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c new file mode 100644 index 000000000..fb7073ac9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem32() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem32 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c new file mode 100644 index 000000000..9e9d663f7 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,58 @@ +/** @file + SetMem64() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + ASSERT ((((UINTN)Buffer) & (sizeof (Value) - 1)) == 0); + ASSERT ((Length & (sizeof (Value) - 1)) == 0); + + return InternalMemSetMem64 (Buffer, Length / sizeof (Value), Value); +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c new file mode 100644 index 000000000..1d54a8afe --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c @@ -0,0 +1,85 @@ +/** @file + SetMem() and SetMemN() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with a byte value, and returns the target buffer. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Buffer)); + + return InternalMemSetMem (Buffer, Length, Value); +} + +/** + Fills a target buffer with a value that is size UINTN, and returns the target buffer. + + This function fills Length bytes of Buffer with the UINTN sized value specified by + Value, and returns Buffer. Value is repeated every sizeof(UINTN) bytes for Length + bytes of Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a UINTN boundary, then ASSERT(). + If Length is not aligned on a UINTN boundary, then ASSERT(). + + @param Buffer The pointer to the target buffer to fill. + @param Length The number of bytes in Buffer to fill. + @param Value The value with which to fill Length bytes of Buffer. + + @return Buffer. + +**/ +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf b/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf new file mode 100644 index 000000000..2556225e1 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf @@ -0,0 +1,55 @@ +## @file +# Instance of Base Memory Library using EFI Boot Services. +# +# Base Memory Library implementation that uses EFI Boot Services +# where possible for size reduction. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiMemoryLib + MODULE_UNI_FILE = UefiMemoryLib.uni + FILE_GUID = f1bbe03d-2f28-4dee-bec7-d98d7a30c36a + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + ScanMem64Wrapper.c + ScanMem32Wrapper.c + ScanMem16Wrapper.c + ScanMem8Wrapper.c + ZeroMemWrapper.c + CompareMemWrapper.c + SetMem64Wrapper.c + SetMem32Wrapper.c + SetMem16Wrapper.c + SetMemWrapper.c + CopyMemWrapper.c + IsZeroBufferWrapper.c + MemLibGeneric.c + MemLibGuid.c + MemLib.c + MemLibInternals.h + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + DebugLib + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni b/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni new file mode 100644 index 000000000..4bb085745 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of Base Memory Library using EFI Boot Services. +// +// Base Memory Library implementation that uses EFI Boot Services +// where possible for size reduction. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Base Memory Library using EFI Boot Services" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Memory Library implementation that uses EFI Boot Services where possible, for size reduction." + diff --git a/roms/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c b/roms/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c new file mode 100644 index 000000000..596411896 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,50 @@ +/** @file + ZeroMem() implementation. + + The following BaseMemoryLib instances contain the same copy of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + BaseMemoryLibOptDxe + BaseMemoryLibOptPei + PeiMemoryLib + UefiMemoryLib + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MemLibInternals.h" + +/** + Fills a target buffer with zeros, and returns the target buffer. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to fill with zeros. + @param Length The number of bytes in Buffer to fill with zeros. + + @return Buffer. + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + if (Length == 0) { + return Buffer; + } + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1)); + return InternalMemZeroMem (Buffer, Length); +} diff --git a/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c new file mode 100644 index 000000000..57eb37c3e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c @@ -0,0 +1,1427 @@ +/** @file + PCI Library using PCI Root Bridge I/O Protocol. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A,M) \ + ASSERT (((A) & (~0xfffffff | (M))) == 0) + +/** + Translate PCI Lib address into format of PCI Root Bridge I/O Protocol. + + @param A The address that encodes the PCI Bus, Device, Function and + Register. + +**/ +#define PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS(A) \ + ((((A) << 4) & 0xff000000) | (((A) >> 4) & 0x00000700) | (((A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) + +// +// Global varible to cache pointer to PCI Root Bridge I/O protocol. +// +EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo = NULL; + +/** + The constructor function caches the pointer to PCI Root Bridge I/O protocol. + + The constructor function locates PCI Root Bridge I/O protocol from protocol database. + 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 always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PciLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID**) &mPciRootBridgeIo); + ASSERT_EFI_ERROR (Status); + ASSERT (mPciRootBridgeIo != NULL); + + return EFI_SUCCESS; +} + +/** + Internal worker function to read a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read() service. + It reads and returns the PCI configuration register specified by Address, + the width of data is specified by Width. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to read + + @return The value read from the PCI configuration register. + +**/ +UINT32 +DxePciLibPciRootBridgeIoReadWorker ( + IN UINTN Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width + ) +{ + UINT32 Data; + + mPciRootBridgeIo->Pci.Read ( + mPciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + + return Data; +} + +/** + Internal worker function to writes a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Write() service. + It writes the PCI configuration register specified by Address with the + value specified by Data. The width of data is specified by Width. + Data is returned. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width The width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +DxePciLibPciRootBridgeIoWriteWorker ( + IN UINTN Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT32 Data + ) +{ + mPciRootBridgeIo->Pci.Write ( + mPciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + return Data; +} + +/** + Registers a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + Registers the PCI device specified by Address so all the PCI configuration registers + associated with that PCI device may be accessed after SetVirtualAddressMap() is called. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + return RETURN_UNSUPPORTED; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) DxePciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + + return (UINT8) DxePciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciWrite8 (Address, (UINT8) (PciRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 (Address, (UINT8) ((PciRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciWrite8 ( + Address, + BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldOr8 (PciRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciWrite8 ( + Address, + BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciWrite8 ( + Address, + BitFieldAndThenOr8 (PciRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) DxePciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + + return (UINT16) DxePciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciWrite16 (Address, (UINT16) (PciRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 (Address, (UINT16) ((PciRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciWrite16 ( + Address, + BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciWrite16 ( + Address, + BitFieldAnd16 (PciRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciWrite16 ( + Address, + BitFieldAndThenOr16 (PciRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return DxePciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + + return DxePciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciWrite32 (Address, PciRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 (Address, (PciRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address The PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciWrite32 ( + Address, + BitFieldWrite32 (PciRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldOr32 (PciRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciWrite32 ( + Address, + BitFieldAnd32 (PciRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address The PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciWrite32 ( + Address, + BitFieldAndThenOr32 (PciRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress The starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size The size in bytes of the transfer. + @param Buffer The pointer to a buffer containing the data to write. + + @return Size written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf new file mode 100644 index 000000000..2e4ff823c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf @@ -0,0 +1,52 @@ +## @file +# PCI Library that layers on top of the PCI Root Bridge I/O Protocol. +# +# This library produces the APIs from the PCI Library and implements these APIs +# by calling into the PCI Root Bridge I/O Protocol. The PCI Root Bridge I/O Protocol is +# typically produced by a chipset specific DXE driver. +# This library binds to the first PCI Root Bridge I/O Protocol in the platform. As a result, +# it should only be used on platforms that contain a single PCI root bridge. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiPciLibPciRootBridgeIo + MODULE_UNI_FILE = UefiPciLibPciRootBridgeIo.uni + FILE_GUID = 90EC42CB-B780-4eb8-8E99-C8E3E5F37530 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION + + CONSTRUCTOR = PciLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + DebugLib + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiPciRootBridgeIoProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni new file mode 100644 index 000000000..3dd5c68b9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni @@ -0,0 +1,20 @@ +// /** @file +// PCI Library that layers on top of the PCI Root Bridge I/O Protocol. +// +// This library produces the APIs from the PCI Library and implements these APIs +// by calling into the PCI Root Bridge I/O Protocol. The PCI Root Bridge I/O Protocol is +// typically produced by a chipset specific DXE driver. +// This library binds to the first PCI Root Bridge I/O Protocol in the platform. As a result, +// it should only be used on platforms that contain a single PCI root bridge. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "PCI Library that layers on top of the PCI Root Bridge I/O Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "This library produces the APIs from the PCI Library and implements these APIs by calling into the PCI Root Bridge I/O Protocol. The PCI Root Bridge I/O Protocol is typically produced by a chipset-specific DXE driver. This library binds to the first PCI Root Bridge I/O Protocol in the platform. As a result, it should only be used on platforms that contain a single PCI root bridge." + diff --git a/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c new file mode 100644 index 000000000..65f2fa307 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c @@ -0,0 +1,1484 @@ +/** @file + PCI Segment Library implementation using PCI Root Bridge I/O Protocol. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciSegmentLib.h" + +// +// Global variable to record data of PCI Root Bridge I/O Protocol instances +// +PCI_ROOT_BRIDGE_DATA *mPciRootBridgeData = NULL; +UINTN mNumberOfPciRootBridges = 0; + +/** + The constructor function caches data of PCI Root Bridge I/O Protocol instances. + + The constructor function locates PCI Root Bridge I/O protocol instances, + and caches the protocol instances, together with their segment numbers and bus ranges. + 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 +PciSegmentLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + HandleCount = 0; + HandleBuffer = NULL; + PciRootBridgeIo = NULL; + Descriptors = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + mNumberOfPciRootBridges = HandleCount; + + mPciRootBridgeData = AllocatePool (HandleCount * sizeof (PCI_ROOT_BRIDGE_DATA)); + ASSERT (mPciRootBridgeData != NULL); + + // + // Traverse all PCI Root Bridge I/O Protocol instances, and record the protocol + // instances, together with their segment numbers and bus ranges. + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo + ); + ASSERT_EFI_ERROR (Status); + + mPciRootBridgeData[Index].PciRootBridgeIo = PciRootBridgeIo; + mPciRootBridgeData[Index].SegmentNumber = PciRootBridgeIo->SegmentNumber; + + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + ASSERT_EFI_ERROR (Status); + + while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) { + if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { + mPciRootBridgeData[Index].MinBusNumber = Descriptors->AddrRangeMin; + mPciRootBridgeData[Index].MaxBusNumber = Descriptors->AddrRangeMax; + break; + } + Descriptors++; + } + ASSERT (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR); + } + + FreePool(HandleBuffer); + + return EFI_SUCCESS; +} + +/** + The destructor function frees memory allocated by constructor. + + The destructor function frees memory for data of protocol instances allocated by constructor. + 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 +PciSegmentLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FreePool (mPciRootBridgeData); + + return EFI_SUCCESS; +} + +/** + According to address, search for the corresponding PCI Root Bridge I/O Protocol instance. + + This internal function extracts segment number and bus number data from address, and + retrieves the corresponding PCI Root Bridge I/O Protocol instance. + + @param Address The address that encodes the Segment, PCI Bus, Device, Function and + Register. + + @return The address for PCI Root Bridge I/O Protocol. + +**/ +EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * +PciSegmentLibSearchForRootBridge ( + IN UINT64 Address + ) +{ + UINTN Index; + UINT64 SegmentNumber; + UINT64 BusNumber; + + for (Index = 0; Index < mNumberOfPciRootBridges; Index++) { + // + // Matches segment number of address with the segment number of protocol instance. + // + SegmentNumber = BitFieldRead64 (Address, 32, 63); + if (SegmentNumber == mPciRootBridgeData[Index].SegmentNumber) { + // + // Matches the bus number of address with bus number range of protocol instance. + // + BusNumber = BitFieldRead64 (Address, 20, 27); + if (BusNumber >= mPciRootBridgeData[Index].MinBusNumber && BusNumber <= mPciRootBridgeData[Index].MaxBusNumber) { + return mPciRootBridgeData[Index].PciRootBridgeIo; + } + } + } + return NULL; +} + +/** + Internal worker function to read a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read() service. + It reads and returns the PCI configuration register specified by Address, + the width of data is specified by Width. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width Width of data to read + + @return The value read from the PCI configuration register. + +**/ +UINT32 +DxePciSegmentLibPciRootBridgeIoReadWorker ( + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width + ) +{ + UINT32 Data; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = PciSegmentLibSearchForRootBridge (Address); + ASSERT (PciRootBridgeIo != NULL); + + PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + + return Data; +} + +/** + Internal worker function to writes a PCI configuration register. + + This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Write() service. + It writes the PCI configuration register specified by Address with the + value specified by Data. The width of data is specifed by Width. + Data is returned. + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Width Width of data to write + @param Data The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +DxePciSegmentLibPciRootBridgeIoWriteWorker ( + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT32 Data + ) +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = PciSegmentLibSearchForRootBridge (Address); + ASSERT (PciRootBridgeIo != NULL); + + PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + Width, + PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), + 1, + &Data + ); + + return Data; +} + +/** + Register a PCI device so PCI configuration registers may be accessed after + SetVirtualAddressMap(). + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @retval RETURN_SUCCESS The PCI device was registered for runtime access. + @retval RETURN_UNSUPPORTED An attempt was made to call this function + after ExitBootServices(). + @retval RETURN_UNSUPPORTED The resources required to access the PCI device + at runtime could not be mapped. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + complete the registration. + +**/ +RETURN_STATUS +EFIAPI +PciSegmentRegisterForRuntimeAccess ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + return RETURN_UNSUPPORTED; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) DxePciSegmentLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint8); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0); + + return (UINT8) DxePciSegmentLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint8, Value); +} + +/** + Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) | OrData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData)); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciSegmentWrite8 ( + Address, + BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) DxePciSegmentLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint16); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1); + + return (UINT16) DxePciSegmentLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint16, Value); +} + +/** + Performs a bitwise OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by OrData, and + writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. This function + must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData)); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData)); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes + the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciSegmentWrite16 ( + Address, + BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return DxePciSegmentLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint32); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3); + + return DxePciSegmentLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint32, Value); +} + +/** + Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + + Reads the 32-bit PCI configuration register specified by Address, performs a bitwise + AND between the read result and the value specified by AndData, and writes the result + to the 32-bit PCI configuration register specified by Address. The value written to + the PCI configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciSegmentWrite32 ( + Address, + BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return Size; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Read a byte if StartAddress is byte aligned + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Read a word if StartAddress is word aligned + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Read as many double words as possible + // + WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Read the last remaining word if exist + // + WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Read the last remaining byte if exist + // + *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress); + } + + return ReturnValue; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If Size > 0 and Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The parameter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN ReturnValue; + + ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0); + ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); + + if (Size == 0) { + return 0; + } + + ASSERT (Buffer != NULL); + + // + // Save Size for return + // + ReturnValue = Size; + + if ((StartAddress & BIT0) != 0) { + // + // Write a byte if StartAddress is byte aligned + // + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Size -= sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { + // + // Write a word if StartAddress is word aligned + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (Size >= sizeof (UINT32)) { + // + // Write as many double words as possible + // + PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer)); + StartAddress += sizeof (UINT32); + Size -= sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (Size >= sizeof (UINT16)) { + // + // Write the last remaining word if exist + // + PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer)); + StartAddress += sizeof (UINT16); + Size -= sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (Size >= sizeof (UINT8)) { + // + // Write the last remaining byte if exist + // + PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return ReturnValue; +} diff --git a/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h new file mode 100644 index 000000000..693702f3e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h @@ -0,0 +1,51 @@ +/** @file + Include file of PciSegmentPciRootBridgeIo Library. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __DXE_PCI_SEGMENT_LIB__ +#define __DXE_PCI_SEGMENT_LIB__ + + +#include + +#include +#include +#include +#include +#include + +#include + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINT32 SegmentNumber; + UINT64 MinBusNumber; + UINT64 MaxBusNumber; +} PCI_ROOT_BRIDGE_DATA; + +/** + Assert the validity of a PCI Segment address. + A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63 + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \ + ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0) + +/** + Translate PCI Lib address into format of PCI Root Bridge I/O Protocol + + @param A The address that encodes the PCI Bus, Device, Function and + Register. + +**/ +#define PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS(A) \ + ((((UINT32)(A) << 4) & 0xff000000) | (((UINT32)(A) >> 4) & 0x00000700) | (((UINT32)(A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) + +#endif diff --git a/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf new file mode 100644 index 000000000..552f384d5 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf @@ -0,0 +1,55 @@ +## @file +# PCI Segment Library that layers on top of the PCI Root Bridge I/O Protocol. +# +# This library produces the APIs from the PCI Library and implements these APIs +# by calling into the PCI Root Bridge I/O Protocols that are present in the platform. +# The PCI Root Bridge I/O Protocols are typically produced by a chipset specific DXE driver. +# This library binds to all of the PCI Root Bridge I/O Protocols in the platform and handles +# the translation from a PCI segment number into a specific PCI Root Bridge I/O Protocol. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiPciSegmentLibPciRootBridgeIo + MODULE_UNI_FILE = UefiPciSegmentLibPciRootBridgeIo.uni + FILE_GUID = C6068612-B6E0-48a3-BB92-60E4A4F89EDF + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciSegmentLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION + + CONSTRUCTOR = PciSegmentLibConstructor + DESTRUCTOR = PciSegmentLibDestructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciSegmentLib.h + PciSegmentLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiBootServicesTableLib + DebugLib + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES + +[Depex.common.DXE_DRIVER, Depex.common.DXE_RUNTIME_DRIVER, Depex.common.DXE_SAL_DRIVER, Depex.common.DXE_SMM_DRIVER] + gEfiPciRootBridgeIoProtocolGuid + diff --git a/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni new file mode 100644 index 000000000..919fa3143 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni @@ -0,0 +1,20 @@ +// /** @file +// PCI Segment Library that layers on top of the PCI Root Bridge I/O Protocol. +// +// This library produces the APIs from the PCI Library and implements these APIs +// by calling into the PCI Root Bridge I/O Protocols that are present in the platform. +// The PCI Root Bridge I/O Protocols are typically produced by a chipset specific DXE driver. +// This library binds to all of the PCI Root Bridge I/O Protocols in the platform and handles +// the translation from a PCI segment number into a specific PCI Root Bridge I/O Protocol. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Layers on top of the PCI Root Bridge I/O Protocol" + +#string STR_MODULE_DESCRIPTION #language en-US "This library produces the APIs from the PCI Library and implements these APIs by calling into the PCI Root Bridge I/O Protocols that are present in the platform. The PCI Root Bridge I/O Protocols are typically produced by a chipset-specific DXE driver. This library binds to all of the PCI Root Bridge I/O Protocols in the platform and handles the translation from a PCI segment number into a specific PCI Root Bridge I/O Protocol." + diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c b/roms/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c new file mode 100644 index 000000000..a2eadafac --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c @@ -0,0 +1,835 @@ +/** @file + UEFI Runtime Library implementation for non IPF processor types. + + This library hides the global variable for the EFI Runtime Services so the + caller does not need to deal with the possibility of being called from an + OS virtual address space. All pointer values are different for a virtual + mapping than from the normal physical mapping at boot services time. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +/// +/// Driver Lib Module Globals +/// +EFI_EVENT mEfiVirtualNotifyEvent; +EFI_EVENT mEfiExitBootServicesEvent; +BOOLEAN mEfiGoneVirtual = FALSE; +BOOLEAN mEfiAtRuntime = FALSE; +EFI_RUNTIME_SERVICES *mInternalRT; + +/** + Set AtRuntime flag as TRUE after ExitBootServices. + + @param[in] Event The Event that is being processed. + @param[in] Context The Event Context. + +**/ +VOID +EFIAPI +RuntimeLibExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mEfiAtRuntime = TRUE; +} + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed. + @param[in] Context The Event Context. +**/ +VOID +EFIAPI +RuntimeLibVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Update global for Runtime Services Table and IO + // + EfiConvertPointer (0, (VOID **) &mInternalRT); + + mEfiGoneVirtual = TRUE; +} + +/** + Initialize runtime Driver Lib if it has not yet been initialized. + It will ASSERT() if gRT is NULL or gBS is NULL. + It will ASSERT() if that operation fails. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @return EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started. +**/ +EFI_STATUS +EFIAPI +RuntimeDriverLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ASSERT (gRT != NULL); + ASSERT (gBS != NULL); + + mInternalRT = gRT; + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + TPL_NOTIFY, + RuntimeLibVirtualNotifyEvent, + NULL, + &mEfiVirtualNotifyEvent + ); + + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + RuntimeLibExitBootServicesEvent, + NULL, + &mEfiExitBootServicesEvent + ); + + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + If a runtime driver exits with an error, it must call this routine + to free the allocated resource before the exiting. + It will ASSERT() if gBS is NULL. + It will ASSERT() if that operation fails. + + @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 Runtime Driver Lib shutdown successfully. + @retval EFI_UNSUPPORTED Runtime Driver lib was not initialized. +**/ +EFI_STATUS +EFIAPI +RuntimeDriverLibDeconstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Close SetVirtualAddressMap () notify function + // + ASSERT (gBS != NULL); + Status = gBS->CloseEvent (mEfiVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CloseEvent (mEfiExitBootServicesEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + This function allows the caller to determine if UEFI ExitBootServices() has been called. + + This function returns TRUE after all the EVT_SIGNAL_EXIT_BOOT_SERVICES functions have + executed as a result of the OS calling ExitBootServices(). Prior to this time FALSE + is returned. This function is used by runtime code to decide it is legal to access + services that go away after ExitBootServices(). + + @retval TRUE The system has finished executing the EVT_SIGNAL_EXIT_BOOT_SERVICES event. + @retval FALSE The system has not finished executing the EVT_SIGNAL_EXIT_BOOT_SERVICES event. + +**/ +BOOLEAN +EFIAPI +EfiAtRuntime ( + VOID + ) +{ + return mEfiAtRuntime; +} + +/** + This function allows the caller to determine if UEFI SetVirtualAddressMap() has been called. + + This function returns TRUE after all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE functions have + executed as a result of the OS calling SetVirtualAddressMap(). Prior to this time FALSE + is returned. This function is used by runtime code to decide it is legal to access services + that go away after SetVirtualAddressMap(). + + @retval TRUE The system has finished executing the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. + @retval FALSE The system has not finished executing the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. + +**/ +BOOLEAN +EFIAPI +EfiGoneVirtual ( + VOID + ) +{ + return mEfiGoneVirtual; +} + + +/** + This service is a wrapper for the UEFI Runtime Service ResetSystem(). + + The ResetSystem()function resets the entire platform, including all processors and devices,and reboots the system. + Calling this interface with ResetType of EfiResetCold causes a system-wide reset. This sets all circuitry within + the system to its initial state. This type of reset is asynchronous to system operation and operates without regard + to cycle boundaries. EfiResetCold is tantamount to a system power cycle. + Calling this interface with ResetType of EfiResetWarm causes a system-wide initialization. The processors are set to + their initial state, and pending cycles are not corrupted. If the system does not support this reset type, then an + EfiResetCold must be performed. + Calling this interface with ResetType of EfiResetShutdown causes the system to enter a power state equivalent to the + ACPI G2/S5 or G3 states. If the system does not support this reset type, then when the system is rebooted, it should + exhibit the EfiResetCold attributes. + The platform may optionally log the parameters from any non-normal reset that occurs. + The ResetSystem() function does not return. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. If the system reset is part of a normal operation, the status code + would be EFI_SUCCESS. If the system reset is due to some type of failure the most appropriate EFI + Status code would be used. + @param DataSizeThe size, in bytes, of ResetData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown the data buffer starts with a + Null-terminated Unicode string, optionally followed by additional binary data. The string is a + description that the caller may use to further indicate the reason for the system reset. ResetData + is only valid if ResetStatus is something other then EFI_SUCCESS. This pointer must be a physical + address. For a ResetType of EfiRestUpdate the data buffer also starts with a Null-terminated string + that is followed by a physical VOID * to an EFI_CAPSULE_HEADER. + +**/ +VOID +EFIAPI +EfiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + mInternalRT->ResetSystem (ResetType, ResetStatus, DataSize, ResetData); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetTime(). + + The GetTime() function returns a time that was valid sometime during the call to the function. + While the returned EFI_TIME structure contains TimeZone and Daylight savings time information, + the actual clock does not maintain these values. The current time zone and daylight saving time + information returned by GetTime() are the values that were last set via SetTime(). + The GetTime() function should take approximately the same amount of time to read the time each + time it is called. All reported device capabilities are to be rounded up. + During runtime, if a PC-AT CMOS device is present in the platform the caller must synchronize + access to the device before calling GetTime(). + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock device's + capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +EfiGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ) +{ + return mInternalRT->GetTime (Time, Capabilities); +} + + +/** + This service is a wrapper for the UEFI Runtime Service SetTime(). + + The SetTime() function sets the real time clock device to the supplied time, and records the + current time zone and daylight savings time information. The SetTime() function is not allowed + to loop based on the current time. For example, if the device does not support a hardware reset + for the sub-resolution time, the code is not to implement the feature by waiting for the time to + wrap. + During runtime, if a PC-AT CMOS device is present in the platform the caller must synchronize + access to the device before calling SetTime(). + + @param Time A pointer to the current time. Type EFI_TIME is defined in the GetTime() + function description. Full error checking is performed on the different + fields of the EFI_TIME structure (refer to the EFI_TIME definition in the + GetTime() function description for full details), and EFI_INVALID_PARAMETER + is returned if any field is out of range. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +EfiSetTime ( + IN EFI_TIME *Time + ) +{ + return mInternalRT->SetTime (Time); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetWakeupTime(). + + The alarm clock time may be rounded from the set alarm clock time to be within the resolution + of the alarm clock device. The resolution of the alarm clock device is defined to be one second. + During runtime, if a PC-AT CMOS device is present in the platform the caller must synchronize + access to the device before calling GetWakeupTime(). + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. Type EFI_TIME is defined in the GetTime() + function description. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Enabled is NULL. + @retval EFI_INVALID_PARAMETER Pending is NULL. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +EfiGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + return mInternalRT->GetWakeupTime (Enabled, Pending, Time); +} + + + +/** + This service is a wrapper for the UEFI Runtime Service SetWakeupTime() + + Setting a system wakeup alarm causes the system to wake up or power on at the set time. + When the alarm fires, the alarm signal is latched until it is acknowledged by calling SetWakeupTime() + to disable the alarm. If the alarm fires before the system is put into a sleeping or off state, + since the alarm signal is latched the system will immediately wake up. If the alarm fires while + the system is off and there is insufficient power to power on the system, the system is powered + on when power is restored. + + @param Enable Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. Type EFI_TIME + is defined in the GetTime() function description. If Enable is FALSE, + then this parameter is optional, and may be NULL. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. + If Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +EfiSetWakeupTime ( + IN BOOLEAN Enable, + IN EFI_TIME *Time OPTIONAL + ) +{ + return mInternalRT->SetWakeupTime (Enable, Time); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetVariable(). + + Each vendor may create and manage its own variables without the risk of name conflicts by + using a unique VendorGuid. When a variable is set its Attributes are supplied to indicate + how the data variable should be stored and maintained by the system. The attributes affect + when the variable may be accessed and volatility of the data. Any attempts to access a variable + that does not have the attribute set for runtime access will yield the EFI_NOT_FOUND error. + If the Data buffer is too small to hold the contents of the variable, the error EFI_BUFFER_TOO_SMALL + is returned and DataSize is set to the required buffer size to obtain the data. + + @param VariableName the name of the vendor's variable, it's a Null-Terminated Unicode String + @param VendorGuid Unify identifier for vendor. + @param Attributes Point to memory location to return the attributes of variable. If the point + is NULL, the parameter would be ignored. + @param DataSize As input, point to the maximum size of return Data-Buffer. + As output, point to the actual size of the returned Data-Buffer. + @param Data Point to return Data-Buffer. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has + been updated with the size needed to complete the request. + @retval EFI_INVALID_PARAMETER VariableName is NULL. + @retval EFI_INVALID_PARAMETER VendorGuid is NULL. + @retval EFI_INVALID_PARAMETER DataSize is NULL. + @retval EFI_INVALID_PARAMETER The DataSize is not too small and Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure. +**/ +EFI_STATUS +EFIAPI +EfiGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + return mInternalRT->GetVariable (VariableName, VendorGuid, Attributes, DataSize, Data); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetNextVariableName(). + + GetNextVariableName() is called multiple times to retrieve the VariableName and VendorGuid of + all variables currently available in the system. On each call to GetNextVariableName() the + previous results are passed into the interface, and on output the interface returns the next + variable name data. When the entire variable list has been returned, the error EFI_NOT_FOUND + is returned. + + @param VariableNameSize As input, point to maximum size of variable name. + As output, point to actual size of variable name. + @param VariableName As input, supplies the last VariableName that was returned by + GetNextVariableName(). + As output, returns the name of variable. The name + string is Null-Terminated Unicode string. + @param VendorGuid As input, supplies the last VendorGuid that was returned by + GetNextVriableName(). + As output, returns the VendorGuid of the current variable. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The next variable was not found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result. + VariableNameSize has been updated with the size needed + to complete the request. + @retval EFI_INVALID_PARAMETER VariableNameSize is NULL. + @retval EFI_INVALID_PARAMETER VariableName is NULL. + @retval EFI_INVALID_PARAMETER VendorGuid is NULL. + @retval EFI_DEVICE_ERROR The variable name could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +EfiGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +{ + return mInternalRT->GetNextVariableName (VariableNameSize, VariableName, VendorGuid); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetNextVariableName() + + Variables are stored by the firmware and may maintain their values across power cycles. Each vendor + may create and manage its own variables without the risk of name conflicts by using a unique VendorGuid. + + @param VariableName The name of the vendor's variable; it's a Null-Terminated + Unicode String + @param VendorGuid Unify identifier for vendor. + @param Attributes Points to a memory location to return the attributes of variable. If the point + is NULL, the parameter would be ignored. + @param DataSize The size in bytes of Data-Buffer. + @param Data Points to the content of 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 was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty Unicode 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 saved due to a hardware failure. + @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_TIME_BASED_AUTHENTICATED_WRITE_ACCESS + 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 +EFIAPI +EfiSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + return mInternalRT->SetVariable (VariableName, VendorGuid, Attributes, DataSize, Data); +} + + +/** + This service is a wrapper for the UEFI Runtime Service GetNextHighMonotonicCount(). + + The platform's monotonic counter is comprised of two 32-bit quantities: the high 32 bits and + the low 32 bits. During boot service time the low 32-bit value is volatile: it is reset to zero + on every system reset and is increased by 1 on every call to GetNextMonotonicCount(). The high + 32-bit value is nonvolatile and is increased by 1 whenever the system resets or whenever the low + 32-bit count (returned by GetNextMonoticCount()) overflows. + + @param HighCount The pointer to returned value. + + @retval EFI_SUCCESS The next high monotonic count was returned. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + @retval EFI_INVALID_PARAMETER HighCount is NULL. + +**/ +EFI_STATUS +EFIAPI +EfiGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +{ + return mInternalRT->GetNextHighMonotonicCount (HighCount); +} + + +/** + This service is a wrapper for the UEFI Runtime Service ConvertPointer(). + + The ConvertPointer() function is used by an EFI component during the SetVirtualAddressMap() operation. + ConvertPointer()must be called using physical address pointers during the execution of SetVirtualAddressMap(). + + @param DebugDisposition Supplies type information for the pointer being converted. + @param Address The pointer to a pointer that is to be fixed to be the + value needed for the new virtual address mapping being + applied. + + @retval EFI_SUCCESS The pointer pointed to by Address was modified. + @retval EFI_NOT_FOUND The pointer pointed to by Address was not found to be part of + the current memory map. This is normally fatal. + @retval EFI_INVALID_PARAMETER Address is NULL. + @retval EFI_INVALID_PARAMETER *Address is NULL and DebugDispositio + +**/ +EFI_STATUS +EFIAPI +EfiConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ) +{ + return gRT->ConvertPointer (DebugDisposition, Address); +} + + +/** + Determines the new virtual address that is to be used on subsequent memory accesses. + + For IA32, x64, and EBC, this service is a wrapper for the UEFI Runtime Service + ConvertPointer(). See the UEFI Specification for details. + For IPF, this function interprets Address as a pointer to an EFI_PLABEL structure + and both the EntryPoint and GP fields of an EFI_PLABEL are converted from physical + to virtiual addressing. Since IPF allows the GP to point to an address outside + a PE/COFF image, the physical to virtual offset for the EntryPoint field is used + to adjust the GP field. The UEFI Runtime Service ConvertPointer() is used to convert + EntryPoint and the status code for this conversion is always returned. If the convertion + of EntryPoint fails, then neither EntryPoint nor GP are modified. See the UEFI + Specification for details on the UEFI Runtime Service ConvertPointer(). + + @param DebugDisposition Supplies type information for the pointer being converted. + @param Address The pointer to a pointer that is to be fixed to be the + value needed for the new virtual address mapping being + applied. + + @return EFI_STATUS value from EfiConvertPointer(). + +**/ +EFI_STATUS +EFIAPI +EfiConvertFunctionPointer ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ) +{ + return EfiConvertPointer (DebugDisposition, Address); +} + + +/** + Convert the standard Lib double linked list to a virtual mapping. + + This service uses EfiConvertPointer() to walk a double linked list and convert all the link + pointers to their virtual mappings. This function is only guaranteed to work during the + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event and calling it at other times has undefined results. + + @param DebugDisposition Supplies type information for the pointer being converted. + @param ListHead Head of linked list to convert. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ) +{ + LIST_ENTRY *Link; + LIST_ENTRY *NextLink; + + // + // For NULL List, return EFI_SUCCESS + // + if (ListHead == NULL) { + return EFI_SUCCESS; + } + + // + // Convert all the ForwardLink & BackLink pointers in the list + // + Link = ListHead; + do { + NextLink = Link->ForwardLink; + + EfiConvertPointer ( + Link->ForwardLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->ForwardLink + ); + + EfiConvertPointer ( + Link->BackLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->BackLink + ); + + Link = NextLink; + } while (Link != ListHead); + return EFI_SUCCESS; +} + + +/** + This service is a wrapper for the UEFI Runtime Service SetVirtualAddressMap(). + + The SetVirtualAddressMap() function is used by the OS loader. The function can only be called + at runtime, and is called by the owner of the system's memory map. I.e., the component which + called ExitBootServices(). All events of type EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE must be signaled + before SetVirtualAddressMap() returns. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. Type + EFI_MEMORY_DESCRIPTOR is defined in the + GetMemoryMap() function description. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is + invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. +**/ +EFI_STATUS +EFIAPI +EfiSetVirtualAddressMap ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN CONST EFI_MEMORY_DESCRIPTOR *VirtualMap + ) +{ + return mInternalRT->SetVirtualAddressMap ( + MemoryMapSize, + DescriptorSize, + DescriptorVersion, + (EFI_MEMORY_DESCRIPTOR *) VirtualMap + ); +} + + +/** + This service is a wrapper for the UEFI Runtime Service UpdateCapsule(). + + Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended + consumption, the firmware may process the capsule immediately. If the payload should persist across a + system reset, the reset value returned from EFI_QueryCapsuleCapabilities must be passed into ResetSystem() + and will cause the capsule to be processed by the firmware as part of the reset process. + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. Each capsules is assumed to + stored in contiguous virtual memory. The capsules in the + CapsuleHeaderArray must be the same capsules as the + ScatterGatherList. The CapsuleHeaderArray must + have the capsules in the same order as the ScatterGatherList. + @param CapsuleCount The number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param ScatterGatherList Physical pointer to a set of + EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the + location in physical memory of a set of capsules. See Related + Definitions for an explanation of how more than one capsule is + passed via this interface. The capsules in the + ScatterGatherList must be in the same order as the + CapsuleHeaderArray. This parameter is only referenced if + the capsules are defined to persist across system reset. + + @retval EFI_SUCCESS Valid capsule was passed. If CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, + the capsule has been successfully processed by the firmware. + @retval EFI_INVALID_PARAMETER CapsuleSize or HeaderSize is NULL. + @retval EFI_INVALID_PARAMETER CapsuleCount is 0 + @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform. + @retval EFI_OUT_OF_RESOURCES There were insufficient resources to process the capsule. + +**/ +EFI_STATUS +EFIAPI +EfiUpdateCapsule ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ) +{ + return mInternalRT->UpdateCapsule ( + CapsuleHeaderArray, + CapsuleCount, + ScatterGatherList + ); +} + + +/** + This service is a wrapper for the UEFI Runtime Service QueryCapsuleCapabilities(). + + The QueryCapsuleCapabilities() function allows a caller to test to see if a capsule or + capsules can be updated via UpdateCapsule(). The Flags values in the capsule header and + size of the entire capsule is checked. + If the caller needs to query for generic capsule capability a fake EFI_CAPSULE_HEADER can be + constructed where CapsuleImageSize is equal to HeaderSize that is equal to sizeof + (EFI_CAPSULE_HEADER). To determine reset requirements, + CAPSULE_FLAGS_PERSIST_ACROSS_RESET should be set in the Flags field of the + EFI_CAPSULE_HEADER. + The firmware must support any capsule that has the + CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag set in EFI_CAPSULE_HEADER. The + firmware sets the policy for what capsules are supported that do not have the + CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag set. + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. The capsules are assumed to + stored in contiguous virtual memory. + @param CapsuleCount The number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param MaximumCapsuleSize On output the maximum size that UpdateCapsule() can + support as an argument to UpdateCapsule() via + CapsuleHeaderArray and ScatterGatherList. + Undefined on input. + @param ResetType Returns the type of reset required for the capsule update. + + @retval EFI_SUCCESS A valid answer was returned. + @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform, and + MaximumCapsuleSize and ResetType are undefined. + @retval EFI_OUT_OF_RESOURCES There were insufficient resources to process the query request. + +**/ +EFI_STATUS +EFIAPI +EfiQueryCapsuleCapabilities ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ) +{ + return mInternalRT->QueryCapsuleCapabilities ( + CapsuleHeaderArray, + CapsuleCount, + MaximumCapsuleSize, + ResetType + ); +} + + +/** + This service is a wrapper for the UEFI Runtime Service QueryVariableInfo(). + + The QueryVariableInfo() function allows a caller to obtain the information about the + maximum size of the storage space available for the EFI variables, the remaining size of the storage + space available for the EFI variables and the maximum size of each individual EFI variable, + associated with the attributes specified. + The returned MaximumVariableStorageSize, RemainingVariableStorageSize, + MaximumVariableSize information may change immediately after the call based on other + runtime activities including asynchronous error events. Also, these values associated with different + attributes are not additive in nature. + + @param Attributes Attributes bitmask to specify the type of variables on + which to return information. Refer to the + GetVariable() function description. + @param MaximumVariableStorageSize + On output the maximum size of the storage space + available for the EFI variables associated with the + attributes specified. + @param RemainingVariableStorageSize + Returns the remaining size of the storage space + available for the EFI variables associated with the + attributes specified.. + @param MaximumVariableSize Returns the maximum size of the individual EFI + variables associated with the attributes specified. + + @retval EFI_SUCCESS A valid answer was returned. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied. + @retval EFI_UNSUPPORTED EFI_UNSUPPORTED The attribute is not supported on this platform, and the + MaximumVariableStorageSize, + RemainingVariableStorageSize, MaximumVariableSize + are undefined. + +**/ +EFI_STATUS +EFIAPI +EfiQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + return mInternalRT->QueryVariableInfo ( + Attributes, + MaximumVariableStorageSize, + RemainingVariableStorageSize, + MaximumVariableSize + ); +} diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf b/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf new file mode 100644 index 000000000..cc4ee1511 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf @@ -0,0 +1,41 @@ +## @file +# Instance of UEFI Runtime Library. +# +# Instance of UEFI Runtime Library, with hooked EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE and +# EVT_SIGNAL_EXIT_BOOT_SERVICES event, to provide runtime services. +# This instance also supports SAL drivers for better performance. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiRuntimeLib + MODULE_UNI_FILE = UefiRuntimeLib.uni + FILE_GUID = b1ee6c28-54aa-4d17-b705-3e28ccb27b2e + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiRuntimeLib|DXE_RUNTIME_DRIVER + + CONSTRUCTOR = RuntimeDriverLibConstruct + DESTRUCTOR = RuntimeDriverLibDeconstruct + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + RuntimeLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DebugLib diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni b/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni new file mode 100644 index 000000000..df5de41dd --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni @@ -0,0 +1,18 @@ +// /** @file +// Instance of UEFI Runtime Library. +// +// Instance of UEFI Runtime Library, with hooked EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE and +// EVT_SIGNAL_EXIT_BOOT_SERVICES event, to provide runtime services. +// This instance also supports SAL drivers for better performance. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of UEFI Runtime Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Instance of UEFI Runtime Library, with hooked EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE and EVT_SIGNAL_EXIT_BOOT_SERVICES event, to provide runtime services. This instance also supports SAL drivers for better performance." + diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c new file mode 100644 index 000000000..e2e91939e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c @@ -0,0 +1,43 @@ +/** @file + UEFI Runtime Services Table Library. + + This library instance retrieve EFI_RUNTIME_SERVICES pointer from EFI system table + in library's constructor. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +EFI_RUNTIME_SERVICES *gRT = NULL; + +/** + The constructor function caches the pointer of Runtime Services Table. + + The constructor function caches the pointer of Runtime Services Table. + It will ASSERT() if the pointer of Runtime Services Table is NULL. + 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 +UefiRuntimeServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache pointer to the EFI Runtime Services Table + // + gRT = SystemTable->RuntimeServices; + ASSERT (gRT != NULL); + return EFI_SUCCESS; +} diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf new file mode 100644 index 000000000..43406208c --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf @@ -0,0 +1,36 @@ +## @file +# UEFI Runtime Services Table Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiRuntimeServicesTableLib + MODULE_UNI_FILE = UefiRuntimeServicesTableLib.uni + FILE_GUID = 19cbbb97-ff61-45ff-8c3f-dfa66dd118c8 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiRuntimeServicesTableLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = UefiRuntimeServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiRuntimeServicesTableLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni new file mode 100644 index 000000000..da320bb70 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni @@ -0,0 +1,16 @@ +// /** @file +// UEFI Runtime Services Table Library implementation. +// +// UEFI Runtime Services Table Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI Runtime Services Table Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "UEFI Runtime Services Table Library implementation." + diff --git a/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c new file mode 100644 index 000000000..512bec500 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c @@ -0,0 +1,2290 @@ +/** @file + UEFI SCSI Library implementation + + Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include +#include +#include +#include +#include +#include + +#include + + + // + // Scsi Command Length + // +#define EFI_SCSI_OP_LENGTH_SIX 0x6 +#define EFI_SCSI_OP_LENGTH_TEN 0xa +#define EFI_SCSI_OP_LENGTH_TWELVE 0xc +#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10 + +// +// The context structure used when non-blocking SCSI read/write operation +// completes. +// +typedef struct { + /// + /// The SCSI request packet to send to the SCSI controller specified by + /// the device handle. + /// + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + /// + /// The length of the output sense data. + /// + UINT8 *SenseDataLength; + /// + /// The status of the SCSI host adapter. + /// + UINT8 *HostAdapterStatus; + /// + /// The status of the target SCSI device. + /// + UINT8 *TargetStatus; + /// + /// The length of the data buffer for the SCSI read/write command. + /// + UINT32 *DataLength; + /// + /// The caller event to be signaled when the SCSI read/write command + /// completes. + /// + EFI_EVENT CallerEvent; +} EFI_SCSI_LIB_ASYNC_CONTEXT; + + + +/** + Execute Test Unit Ready SCSI command on a specific SCSI target. + + Executes the Test Unit Ready command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance + for the specific SCSI target. + @param[in] Timeout The timeout in 100 ns units to use for the execution + of this SCSI Request Packet. A Timeout value of + zero means that this function will wait indefinitely + for the SCSI Request Packet to execute. If Timeout + is greater than zero, then this function will return + EFI_TIMEOUT if the time required to execute the SCSI + Request Packet is greater than Timeout. + @param[in, out] SenseData A pointer to sense data that was generated by + the execution of the SCSI Request Packet. This + buffer must be allocated by the caller. + If SenseDataLength is 0, then this parameter is + optional and may be NULL. + @param[in, out] SenseDataLength On input, a pointer to the length in bytes of + the SenseData buffer. On output, a pointer to + the number of bytes written to the SenseData buffer. + @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces + the SCSI bus containing the SCSI target specified by + ScsiIo when the SCSI Request Packet was executed. + See the EFI SCSI I/O Protocol in the UEFI Specification + for details on the possible return values. + @param[out] TargetStatus The status returned by the SCSI target specified + by ScsiIo when the SCSI Request Packet was executed + on the SCSI Host Controller. See the EFI SCSI I/O + Protocol in the UEFI Specification for details on + the possible return values. + + @retval EFI_SUCCESS The command was executed successfully. + See HostAdapterStatus, TargetStatus, SenseDataLength, + and SenseData in that order for additional status + information. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. The SCSI Request Packet was not sent, so + no additional status information is available. + The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in that + order for additional status information. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). The SCSI Request Packet was not + sent, so no additional status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request + Packet to execute. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for + additional status information. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiTestUnitReadyCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = NULL; + CommandPacket.InTransferLength= 0; + CommandPacket.OutDataBuffer = NULL; + CommandPacket.OutTransferLength= 0; + CommandPacket.SenseData = SenseData; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Test Unit Ready Command + // + Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY; + CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + + return Status; +} + + +/** + Execute Inquiry SCSI command on a specific SCSI target. + + Executes the Inquiry command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If InquiryDataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer + must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance + for the specific SCSI target. + @param[in] Timeout The timeout in 100 ns units to use for the + execution of this SCSI Request Packet. A Timeout + value of zero means that this function will wait + indefinitely for the SCSI Request Packet to execute. + If Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the SCSI Request Packet is greater than Timeout. + @param[in, out] SenseData A pointer to sense data that was generated + by the execution of the SCSI Request Packet. + This buffer must be allocated by the caller. + If SenseDataLength is 0, then this parameter + is optional and may be NULL. + @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. + On output, the number of bytes written to the SenseData buffer. + @param[out] HostAdapterStatus The status of the SCSI Host Controller that + produces the SCSI bus containing the SCSI + target specified by ScsiIo when the SCSI + Request Packet was executed. See the EFI + SCSI I/O Protocol in the UEFI Specification + for details on the possible return values. + @param[out] TargetStatus The status returned by the SCSI target specified + by ScsiIo when the SCSI Request Packet was + executed on the SCSI Host Controller. + See the EFI SCSI I/O Protocol in the UEFI + Specification for details on the possible + return values. + @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated + by the execution of the SCSI Request Packet. + This buffer must be allocated by the caller. + If InquiryDataLength is 0, then this parameter + is optional and may be NULL. + @param[in, out] InquiryDataLength On input, a pointer to the length in bytes + of the InquiryDataBuffer buffer. + On output, a pointer to the number of bytes + written to the InquiryDataBuffer buffer. + @param[in] EnableVitalProductData If TRUE, then the supported vital product + data for the PageCode is returned in InquiryDataBuffer. + If FALSE, then the standard inquiry data is + returned in InquiryDataBuffer and PageCode is ignored. + @param[in] PageCode The page code of the vital product data. + It's ignored if EnableVitalProductData is FALSE. + + @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in that order + for additional status information. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire + InquiryDataBuffer could not be transferred. The actual + number of bytes transferred is returned in InquiryDataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there + are too many SCSI Command Packets already queued. + The SCSI Request Packet was not sent, so no additional + status information is available. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI + Request Packet. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for additional + status information. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not + supported by the SCSI initiator(i.e., SCSI Host Controller). + The SCSI Request Packet was not sent, so no additional + status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request + Packet to execute. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for + additional status information. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiInquiryCommandEx ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *InquiryDataBuffer, OPTIONAL + IN OUT UINT32 *InquiryDataLength, + IN BOOLEAN EnableVitalProductData, + IN UINT8 PageCode + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (InquiryDataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = InquiryDataBuffer; + CommandPacket.InTransferLength= *InquiryDataLength; + CommandPacket.SenseData = SenseData; + CommandPacket.SenseDataLength = *SenseDataLength; + CommandPacket.Cdb = Cdb; + + Cdb[0] = EFI_SCSI_OP_INQUIRY; + if (EnableVitalProductData) { + Cdb[1] |= 0x01; + Cdb[2] = PageCode; + } + + if (*InquiryDataLength > 0xff) { + *InquiryDataLength = 0xff; + } + + Cdb[4] = (UINT8) (*InquiryDataLength); + CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *InquiryDataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Inquiry SCSI command on a specific SCSI target. + + Executes the Inquiry command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If InquiryDataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer + must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance + for the specific SCSI target. + @param[in] Timeout The timeout in 100 ns units to use for the + execution of this SCSI Request Packet. A Timeout + value of zero means that this function will wait + indefinitely for the SCSI Request Packet to execute. + If Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the SCSI Request Packet is greater than Timeout. + @param[in, out] SenseData A pointer to sense data that was generated + by the execution of the SCSI Request Packet. + This buffer must be allocated by the caller. + If SenseDataLength is 0, then this parameter + is optional and may be NULL. + @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. + On output, the number of bytes written to the SenseData buffer. + @param[out] HostAdapterStatus The status of the SCSI Host Controller that + produces the SCSI bus containing the SCSI + target specified by ScsiIo when the SCSI + Request Packet was executed. See the EFI + SCSI I/O Protocol in the UEFI Specification + for details on the possible return values. + @param[out] TargetStatus The status returned by the SCSI target specified + by ScsiIo when the SCSI Request Packet was + executed on the SCSI Host Controller. + See the EFI SCSI I/O Protocol in the UEFI + Specification for details on the possible + return values. + @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated + by the execution of the SCSI Request Packet. + This buffer must be allocated by the caller. + If InquiryDataLength is 0, then this parameter + is optional and may be NULL. + @param[in, out] InquiryDataLength On input, a pointer to the length in bytes + of the InquiryDataBuffer buffer. + On output, a pointer to the number of bytes + written to the InquiryDataBuffer buffer. + @param[in] EnableVitalProductData If TRUE, then the supported vital product + data is returned in InquiryDataBuffer. + If FALSE, then the standard inquiry data is + returned in InquiryDataBuffer. + + @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in that order + for additional status information. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire + InquiryDataBuffer could not be transferred. The actual + number of bytes transferred is returned in InquiryDataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there + are too many SCSI Command Packets already queued. + The SCSI Request Packet was not sent, so no additional + status information is available. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI + Request Packet. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for additional + status information. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not + supported by the SCSI initiator(i.e., SCSI Host Controller). + The SCSI Request Packet was not sent, so no additional + status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request + Packet to execute. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for + additional status information. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiInquiryCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *InquiryDataBuffer, OPTIONAL + IN OUT UINT32 *InquiryDataLength, + IN BOOLEAN EnableVitalProductData + ) +{ + return ScsiInquiryCommandEx ( + ScsiIo, + Timeout, + SenseData, + SenseDataLength, + HostAdapterStatus, + TargetStatus, + InquiryDataBuffer, + InquiryDataLength, + EnableVitalProductData, + 0 + ); +} + +/** + Execute Mode Sense(10) SCSI command on a specific SCSI target. + + Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout + after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters + are used to construct the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance + for the specific SCSI target. + @param[in] Timeout The timeout in 100 ns units to use for the + execution of this SCSI Request Packet. A Timeout + value of zero means that this function will wait + indefinitely for the SCSI Request Packet to execute. + If Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the SCSI Request Packet is greater than Timeout. + @param[in, out] SenseData A pointer to sense data that was generated + by the execution of the SCSI Request Packet. + This buffer must be allocated by the caller. + If SenseDataLength is 0, then this parameter + is optional and may be NULL. + @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. + On output, the number of bytes written to the SenseData buffer. + @param[out] HostAdapterStatus The status of the SCSI Host Controller that + produces the SCSI bus containing the SCSI target + specified by ScsiIo when the SCSI Request Packet + was executed. See the EFI SCSI I/O Protocol in the + UEFI Specification for details on the possible + return values. + @param[out] TargetStatus The status returned by the SCSI target specified + by ScsiIo when the SCSI Request Packet was executed + on the SCSI Host Controller. See the EFI SCSI + I/O Protocol in the UEFI Specification for details + on the possible return values. + @param[in, out] DataBuffer A pointer to data that was generated by the + execution of the SCSI Request Packet. This + buffer must be allocated by the caller. If + DataLength is 0, then this parameter is optional + and may be NULL. + @param[in, out] DataLength On input, a pointer to the length in bytes of + the DataBuffer buffer. On output, a pointer + to the number of bytes written to the DataBuffer + buffer. + @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command. + @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. + @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. + + @retval EFI_SUCCESS The command was executed successfully. + See HostAdapterStatus, TargetStatus, SenseDataLength, + and SenseData in that order for additional status information. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the + entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already queued. + The SCSI Request Packet was not sent, so no additional + status information is available. The caller may retry + again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + SCSI Request Packet. See HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order for + additional status information. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). The SCSI Request Packet was not + sent, so no additional status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI + Request Packet to execute. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in that + order for additional status information. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiModeSense10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT8 DBDField, OPTIONAL + IN UINT8 PageControl, + IN UINT8 PageCode + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Mode Sense (10) Command + // + Cdb[0] = EFI_SCSI_OP_MODE_SEN10; + // + // DBDField is in Cdb[1] bit3 of (bit7..0) + // + Cdb[1] = (UINT8) ((DBDField << 3) & 0x08); + // + // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0 + // + Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f)); + Cdb[7] = (UINT8) (*DataLength >> 8); + Cdb[8] = (UINT8) (*DataLength); + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Request Sense SCSI command on a specific SCSI target. + + Executes the Request Sense command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are + too many SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiRequestSenseCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = SenseData; + CommandPacket.SenseData = NULL; + CommandPacket.InTransferLength= *SenseDataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Request Sense Command + // + Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE; + Cdb[4] = (UINT8) (*SenseDataLength); + + CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = 0; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = (UINT8) CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Read Capacity SCSI command on a specific SCSI target. + + Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] Pmi Partial medium indicator. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire + DataBuffer could not be transferred. The actual + number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiReadCapacityCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN BOOLEAN Pmi + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read Capacity Command + // + Cdb[0] = EFI_SCSI_OP_READ_CAPACITY; + if (!Pmi) { + // + // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO. + // + ZeroMem ((Cdb + 2), 4); + } else { + Cdb[8] |= 0x01; + } + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Read Capacity SCSI 16 command on a specific SCSI target. + + Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] Pmi Partial medium indicator. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire + DataBuffer could not be transferred. The actual + number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiReadCapacity16Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN BOOLEAN Pmi + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[16]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 16); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read Capacity Command + // + Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16; + Cdb[1] = 0x10; + if (!Pmi) { + // + // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO. + // + ZeroMem ((Cdb + 2), 8); + } else { + Cdb[14] |= 0x01; + } + + Cdb[13] = 0x20; + CommandPacket.CdbLength = 16; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Read(10) SCSI command on a specific SCSI target. + + Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout + after Timeout 100 ns units. The StartLba and SectorSize parameters are used to + construct the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer Read 10 command data. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiRead10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read (10) Command + // + Cdb[0] = EFI_SCSI_OP_READ10; + WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba)); + WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize)); + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Write(10) SCSI command on a specific SCSI target. + + Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct + the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiWrite10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.OutDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.OutTransferLength = *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Write (10) Command + // + Cdb[0] = EFI_SCSI_OP_WRITE10; + Cdb[1] = EFI_SCSI_BLOCK_FUA; + WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba)); + WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize)); + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.OutTransferLength; + + return Status; +} + +/** + Execute Read(16) SCSI command on a specific SCSI target. + + Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout + after Timeout 100 ns units. The StartLba and SectorSize parameters are used to + construct the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer Read 16 command data. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiRead16Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT64 StartLba, + IN UINT32 SectorSize + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength = *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read (16) Command + // + Cdb[0] = EFI_SCSI_OP_READ16; + WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); + WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Write(16) SCSI command on a specific SCSI target. + + Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct + the CDB for this SCSI command. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiWrite16Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT64 StartLba, + IN UINT32 SectorSize + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN); + + CommandPacket.Timeout = Timeout; + CommandPacket.OutDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.OutTransferLength = *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Write (16) Command + // + Cdb[0] = EFI_SCSI_OP_WRITE16; + Cdb[1] = EFI_SCSI_BLOCK_FUA; + WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); + WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; + CommandPacket.DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.OutTransferLength; + + return Status; +} + + +/** + Execute Security Protocol In SCSI command on a specific SCSI target. + + Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If TransferLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in] SecurityProtocol The Security Protocol to use. + @param[in] SecurityProtocolSpecific The Security Protocol Specific data. + @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the + SECURITY PROTOCOL IN command. + @param[in] DataLength The size in bytes of the data buffer. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[out] TransferLength A pointer to a buffer to store the size in + bytes of the data written to the data buffer. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in TransferLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiSecurityProtocolInCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN UINT8 SecurityProtocol, + IN UINT16 SecurityProtocolSpecific, + IN BOOLEAN Inc512, + IN UINTN DataLength, + IN OUT VOID *DataBuffer, OPTIONAL + OUT UINTN *TransferLength + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (ScsiIo != NULL); + ASSERT (TransferLength != NULL); + ASSERT (DataLength <= MAX_UINT32); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength = (UINT32) DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Security Protocol In Command + // + Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_IN; + Cdb[1] = SecurityProtocol; + WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific)); + + if (Inc512) { + if (DataLength % 512 != 0) { + return EFI_INVALID_PARAMETER; + } + Cdb[4] = BIT7; + WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512)); + } else { + WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength)); + } + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *TransferLength = (UINTN) CommandPacket.InTransferLength; + + return Status; +} + + +/** + Execute Security Protocol Out SCSI command on a specific SCSI target. + + Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo. + If Timeout is zero, then this function waits indefinitely for the command to complete. + If Timeout is greater than zero, then the command is executed and will timeout after + Timeout 100 ns units. + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer + alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER + gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in] SecurityProtocol The Security Protocol to use. + @param[in] SecurityProtocolSpecific The Security Protocol Specific data. + @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the + SECURITY PROTOCOL OUT command. + @param[in] DataLength The size in bytes of the transfer data. + @param[in, out] DataBuffer A pointer to a data buffer. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could + not be transferred. The actual number of bytes transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by + the SCSI initiator(i.e., SCSI Host Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid. + +**/ +EFI_STATUS +EFIAPI +ScsiSecurityProtocolOutCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN UINT8 SecurityProtocol, + IN UINT16 SecurityProtocolSpecific, + IN BOOLEAN Inc512, + IN UINTN DataLength, + IN OUT VOID *DataBuffer OPTIONAL + ) +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + EFI_STATUS Status; + UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE]; + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (ScsiIo != NULL); + ASSERT (DataLength <= MAX_UINT32); + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE); + + CommandPacket.Timeout = Timeout; + CommandPacket.OutDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.OutTransferLength = (UINT32) DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Security Protocol Out Command + // + Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT; + Cdb[1] = SecurityProtocol; + WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific)); + + if (Inc512) { + if (DataLength % 512 != 0) { + return EFI_INVALID_PARAMETER; + } + Cdb[4] = BIT7; + WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512)); + } else { + WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength)); + } + + CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE; + CommandPacket.DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + + return Status; +} + + +/** + Internal helper notify function in which update the result of the + non-blocking SCSI Read/Write commands and signal caller event. + + @param Event The instance of EFI_EVENT. + @param Context The parameter passed in. + +**/ +VOID +EFIAPI +ScsiLibNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext; + EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket; + EFI_EVENT CallerEvent; + + LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *) Context; + CommandPacket = &LibContext->CommandPacket; + CallerEvent = LibContext->CallerEvent; + + // + // Update SCSI Read/Write operation results + // + *LibContext->SenseDataLength = CommandPacket->SenseDataLength; + *LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus; + *LibContext->TargetStatus = CommandPacket->TargetStatus; + if (CommandPacket->InDataBuffer != NULL) { + *LibContext->DataLength = CommandPacket->InTransferLength; + } else { + *LibContext->DataLength = CommandPacket->OutTransferLength; + } + + if (CommandPacket->Cdb != NULL) { + FreePool (CommandPacket->Cdb); + } + FreePool (Context); + + gBS->CloseEvent (Event); + gBS->SignalEvent (CallerEvent); +} + + +/** + Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI + target. + + Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo. + When Event is NULL, blocking command will be executed. Otherwise non-blocking + command will be executed. + For blocking I/O, if Timeout is zero, this function will wait indefinitely + for the command to complete. If Timeout is greater than zero, then the + command is executed and will timeout after Timeout 100 ns units. + For non-blocking I/O, if Timeout is zero, Event will be signaled only after + the command to completes. If Timeout is greater than zero, Event will also be + signaled after Timeout 100 ns units. + The StartLba and SectorSize parameters are used to construct the CDB for this + SCSI command. + + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer Read 16 command data. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks + of data that shall be transferred. + @param[in] Event If the SCSI target does not support + non-blocking I/O, then Event is ignored, + and blocking I/O is performed. If Event + is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking + I/O is supported, then non-blocking I/O + is performed, and Event will be signaled + when the SCSI Read(10) command + completes. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, + but the entire DataBuffer could not be + transferred. The actual number of bytes + transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be + sent because there are too many SCSI + Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI + Request Packet is not supported by the + SCSI initiator(i.e., SCSI Host + Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the + SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet + are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due + to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +ScsiRead10CommandEx ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize, + IN EFI_EVENT Event OPTIONAL + ) +{ + EFI_SCSI_LIB_ASYNC_CONTEXT *Context; + EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket; + EFI_STATUS Status; + UINT8 *Cdb; + EFI_EVENT SelfEvent; + + if (Event == NULL) { + return ScsiRead10Command ( + ScsiIo, + Timeout, + SenseData, + SenseDataLength, + HostAdapterStatus, + TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + } + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT)); + if (Context == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN); + if (Cdb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Context->SenseDataLength = SenseDataLength; + Context->HostAdapterStatus = HostAdapterStatus; + Context->TargetStatus = TargetStatus; + Context->CallerEvent = Event; + + CommandPacket = &Context->CommandPacket; + CommandPacket->Timeout = Timeout; + CommandPacket->InDataBuffer = DataBuffer; + CommandPacket->SenseData = SenseData; + CommandPacket->InTransferLength = *DataLength; + CommandPacket->Cdb = Cdb; + // + // Fill Cdb for Read (10) Command + // + Cdb[0] = EFI_SCSI_OP_READ10; + WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba)); + WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize)); + + CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket->DataDirection = EFI_SCSI_DATA_IN; + CommandPacket->SenseDataLength = *SenseDataLength; + + // + // Create Event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ScsiLibNotify, + Context, + &SelfEvent + ); + if (EFI_ERROR(Status)) { + goto ErrorExit; + } + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent); + if (EFI_ERROR(Status)) { + // + // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand() + // returns with error, close the event here. + // + gBS->CloseEvent (SelfEvent); + goto ErrorExit; + } else { + return EFI_SUCCESS; + } + +ErrorExit: + if (Context != NULL) { + FreePool (Context); + } + + return Status; +} + + +/** + Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI + target. + + Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo. + When Event is NULL, blocking command will be executed. Otherwise non-blocking + command will be executed. + For blocking I/O, if Timeout is zero, this function will wait indefinitely + for the command to complete. If Timeout is greater than zero, then the + command is executed and will timeout after Timeout 100 ns units. + For non-blocking I/O, if Timeout is zero, Event will be signaled only after + the command to completes. If Timeout is greater than zero, Event will also be + signaled after Timeout 100 ns units. + The StartLba and SectorSize parameters are used to construct the CDB for this + SCSI command. + + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks + of data that shall be transferred. + @param[in] Event If the SCSI target does not support + non-blocking I/O, then Event is ignored, + and blocking I/O is performed. If Event + is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking + I/O is supported, then non-blocking I/O + is performed, and Event will be signaled + when the SCSI Write(10) command + completes. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, + but the entire DataBuffer could not be + transferred. The actual number of bytes + transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be + sent because there are too many SCSI + Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI + Request Packet is not supported by the + SCSI initiator(i.e., SCSI Host + Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the + SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet + are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due + to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +ScsiWrite10CommandEx ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize, + IN EFI_EVENT Event OPTIONAL + ) +{ + EFI_SCSI_LIB_ASYNC_CONTEXT *Context; + EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket; + EFI_STATUS Status; + UINT8 *Cdb; + EFI_EVENT SelfEvent; + + if (Event == NULL) { + return ScsiWrite10Command ( + ScsiIo, + Timeout, + SenseData, + SenseDataLength, + HostAdapterStatus, + TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + } + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT)); + if (Context == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN); + if (Cdb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Context->SenseDataLength = SenseDataLength; + Context->HostAdapterStatus = HostAdapterStatus; + Context->TargetStatus = TargetStatus; + Context->CallerEvent = Event; + + CommandPacket = &Context->CommandPacket; + CommandPacket->Timeout = Timeout; + CommandPacket->OutDataBuffer = DataBuffer; + CommandPacket->SenseData = SenseData; + CommandPacket->OutTransferLength = *DataLength; + CommandPacket->Cdb = Cdb; + // + // Fill Cdb for Write (10) Command + // + Cdb[0] = EFI_SCSI_OP_WRITE10; + WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba)); + WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize)); + + CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN; + CommandPacket->DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket->SenseDataLength = *SenseDataLength; + + // + // Create Event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ScsiLibNotify, + Context, + &SelfEvent + ); + if (EFI_ERROR(Status)) { + goto ErrorExit; + } + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent); + if (EFI_ERROR(Status)) { + // + // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand() + // returns with error, close the event here. + // + gBS->CloseEvent (SelfEvent); + goto ErrorExit; + } else { + return EFI_SUCCESS; + } + +ErrorExit: + if (Context != NULL) { + FreePool (Context); + } + + return Status; +} + + +/** + Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI + target. + + Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo. + When Event is NULL, blocking command will be executed. Otherwise non-blocking + command will be executed. + For blocking I/O, if Timeout is zero, this function will wait indefinitely + for the command to complete. If Timeout is greater than zero, then the + command is executed and will timeout after Timeout 100 ns units. + For non-blocking I/O, if Timeout is zero, Event will be signaled only after + the command to completes. If Timeout is greater than zero, Event will also be + signaled after Timeout 100 ns units. + The StartLba and SectorSize parameters are used to construct the CDB for this + SCSI command. + + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo A pointer to SCSI IO protocol. + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer Read 16 command data. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks + of data that shall be transferred. + @param[in] Event If the SCSI target does not support + non-blocking I/O, then Event is ignored, + and blocking I/O is performed. If Event + is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking + I/O is supported, then non-blocking I/O + is performed, and Event will be signaled + when the SCSI Read(16) command + completes. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, + but the entire DataBuffer could not be + transferred. The actual number of bytes + transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be + sent because there are too many SCSI + Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI + Request Packet is not supported by the + SCSI initiator(i.e., SCSI Host + Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the + SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet + are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due + to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +ScsiRead16CommandEx ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT64 StartLba, + IN UINT32 SectorSize, + IN EFI_EVENT Event OPTIONAL + ) +{ + EFI_SCSI_LIB_ASYNC_CONTEXT *Context; + EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket; + EFI_STATUS Status; + UINT8 *Cdb; + EFI_EVENT SelfEvent; + + if (Event == NULL) { + return ScsiRead16Command ( + ScsiIo, + Timeout, + SenseData, + SenseDataLength, + HostAdapterStatus, + TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + } + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT)); + if (Context == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN); + if (Cdb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Context->SenseDataLength = SenseDataLength; + Context->HostAdapterStatus = HostAdapterStatus; + Context->TargetStatus = TargetStatus; + Context->CallerEvent = Event; + + CommandPacket = &Context->CommandPacket; + CommandPacket->Timeout = Timeout; + CommandPacket->InDataBuffer = DataBuffer; + CommandPacket->SenseData = SenseData; + CommandPacket->InTransferLength = *DataLength; + CommandPacket->Cdb = Cdb; + // + // Fill Cdb for Read (16) Command + // + Cdb[0] = EFI_SCSI_OP_READ16; + WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); + WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); + + CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; + CommandPacket->DataDirection = EFI_SCSI_DATA_IN; + CommandPacket->SenseDataLength = *SenseDataLength; + + // + // Create Event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ScsiLibNotify, + Context, + &SelfEvent + ); + if (EFI_ERROR(Status)) { + goto ErrorExit; + } + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent); + if (EFI_ERROR(Status)) { + // + // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand() + // returns with error, close the event here. + // + gBS->CloseEvent (SelfEvent); + goto ErrorExit; + } else { + return EFI_SUCCESS; + } + +ErrorExit: + if (Context != NULL) { + FreePool (Context); + } + + return Status; +} + + +/** + Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI + target. + + Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo. + When Event is NULL, blocking command will be executed. Otherwise non-blocking + command will be executed. + For blocking I/O, if Timeout is zero, this function will wait indefinitely + for the command to complete. If Timeout is greater than zero, then the + command is executed and will timeout after Timeout 100 ns units. + For non-blocking I/O, if Timeout is zero, Event will be signaled only after + the command to completes. If Timeout is greater than zero, Event will also be + signaled after Timeout 100 ns units. + The StartLba and SectorSize parameters are used to construct the CDB for this + SCSI command. + + If ScsiIo is NULL, then ASSERT(). + If SenseDataLength is NULL, then ASSERT(). + If HostAdapterStatus is NULL, then ASSERT(). + If TargetStatus is NULL, then ASSERT(). + If DataLength is NULL, then ASSERT(). + + If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet + buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise + EFI_INVALID_PARAMETER gets returned. + + @param[in] ScsiIo SCSI IO Protocol to use + @param[in] Timeout The length of timeout period. + @param[in, out] SenseData A pointer to output sense data. + @param[in, out] SenseDataLength The length of output sense data. + @param[out] HostAdapterStatus The status of Host Adapter. + @param[out] TargetStatus The status of the target. + @param[in, out] DataBuffer A pointer to a data buffer. + @param[in, out] DataLength The length of data buffer. + @param[in] StartLba The start address of LBA. + @param[in] SectorSize The number of contiguous logical blocks + of data that shall be transferred. + @param[in] Event If the SCSI target does not support + non-blocking I/O, then Event is ignored, + and blocking I/O is performed. If Event + is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking + I/O is supported, then non-blocking I/O + is performed, and Event will be signaled + when the SCSI Write(16) command + completes. + + @retval EFI_SUCCESS Command is executed successfully. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, + but the entire DataBuffer could not be + transferred. The actual number of bytes + transferred is returned in DataLength. + @retval EFI_NOT_READY The SCSI Request Packet could not be + sent because there are too many SCSI + Command Packets already queued. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to send SCSI Request Packet. + @retval EFI_UNSUPPORTED The command described by the SCSI + Request Packet is not supported by the + SCSI initiator(i.e., SCSI Host + Controller) + @retval EFI_TIMEOUT A timeout occurred while waiting for the + SCSI Request Packet to execute. + @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet + are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due + to a lack of resources. + +**/ +EFI_STATUS +EFIAPI +ScsiWrite16CommandEx ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN OUT VOID *SenseData, OPTIONAL + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *DataBuffer, OPTIONAL + IN OUT UINT32 *DataLength, + IN UINT64 StartLba, + IN UINT32 SectorSize, + IN EFI_EVENT Event OPTIONAL + ) +{ + EFI_SCSI_LIB_ASYNC_CONTEXT *Context; + EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket; + EFI_STATUS Status; + UINT8 *Cdb; + EFI_EVENT SelfEvent; + + if (Event == NULL) { + return ScsiWrite16Command ( + ScsiIo, + Timeout, + SenseData, + SenseDataLength, + HostAdapterStatus, + TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + } + + ASSERT (SenseDataLength != NULL); + ASSERT (HostAdapterStatus != NULL); + ASSERT (TargetStatus != NULL); + ASSERT (DataLength != NULL); + ASSERT (ScsiIo != NULL); + + Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT)); + if (Context == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN); + if (Cdb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Context->SenseDataLength = SenseDataLength; + Context->HostAdapterStatus = HostAdapterStatus; + Context->TargetStatus = TargetStatus; + Context->CallerEvent = Event; + + CommandPacket = &Context->CommandPacket; + CommandPacket->Timeout = Timeout; + CommandPacket->OutDataBuffer = DataBuffer; + CommandPacket->SenseData = SenseData; + CommandPacket->OutTransferLength = *DataLength; + CommandPacket->Cdb = Cdb; + // + // Fill Cdb for Write (16) Command + // + Cdb[0] = EFI_SCSI_OP_WRITE16; + WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); + WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); + + CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; + CommandPacket->DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket->SenseDataLength = *SenseDataLength; + + // + // Create Event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ScsiLibNotify, + Context, + &SelfEvent + ); + if (EFI_ERROR(Status)) { + goto ErrorExit; + } + + Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent); + if (EFI_ERROR(Status)) { + // + // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand() + // returns with error, close the event here. + // + gBS->CloseEvent (SelfEvent); + goto ErrorExit; + } else { + return EFI_SUCCESS; + } + +ErrorExit: + if (Context != NULL) { + FreePool (Context); + } + + return Status; +} diff --git a/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf new file mode 100644 index 000000000..fa1970e1e --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf @@ -0,0 +1,42 @@ +## @file +# Uefi Scsi Library Instance. +# +# This libarary provides the functions to submit Scsi commands defined +# in SCSI-2 specification for scsi device. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiScsiLib + MODULE_UNI_FILE = UefiScsiLib.uni + FILE_GUID = 280E42C3-826E-4573-9772-B74EF1086D95 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiScsiLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiScsiLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + diff --git a/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni new file mode 100644 index 000000000..39bcf6440 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Uefi Scsi Library Instance. +// +// This libarary provides the functions to submit Scsi commands defined +// in SCSI-2 specification for scsi device. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI SCSI Library Instance" + +#string STR_MODULE_DESCRIPTION #language en-US "This library provides the functions to submit SCSI commands defined in SCSI-2 specification for SCSI devices." + diff --git a/roms/edk2/MdePkg/Library/UefiUsbLib/Hid.c b/roms/edk2/MdePkg/Library/UefiUsbLib/Hid.c new file mode 100644 index 000000000..1d6555271 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiUsbLib/Hid.c @@ -0,0 +1,482 @@ +/** @file + + The library provides USB HID Class standard and specific requests defined + in USB HID Firmware Specification 7 section : Requests. + + Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiUsbLibInternal.h" + +// +// Hid RequestType Bits specifying characteristics of request. +// Valid values are 10100001b (0xa1) or 00100001b (0x21). +// The following description: +// 7 Data transfer direction +// 0 = Host to device +// 1 = Device to host +// 6..5 Type +// 1 = Class +// 4..0 Recipient +// 1 = Interface +// + +/** + Get the descriptor of the specified USB HID interface. + + Submit a USB get HID descriptor request for the USB device specified by UsbIo + and Interface and return the HID descriptor in HidDescriptor. + If UsbIo is NULL, then ASSERT(). + If HidDescriptor is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the HID interface on the USB target. + @param HidDescriptor The pointer to the USB HID descriptor that was retrieved from + the specified USB target and interface. Type EFI_USB_HID_DESCRIPTOR + is defined in the MDE Package Industry Standard include file Usb.h. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbGetHidDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + OUT EFI_USB_HID_DESCRIPTOR *HidDescriptor + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT(UsbIo != NULL); + ASSERT(HidDescriptor != NULL); + + Request.RequestType = USB_HID_GET_DESCRIPTOR_REQ_TYPE; + Request.Request = USB_REQ_GET_DESCRIPTOR; + Request.Value = (UINT16) (USB_DESC_TYPE_HID << 8); + Request.Index = Interface; + Request.Length = (UINT16) sizeof (EFI_USB_HID_DESCRIPTOR); + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + HidDescriptor, + sizeof (EFI_USB_HID_DESCRIPTOR), + &Status + ); + + return Result; + +} + +/** + Get the report descriptor of the specified USB HID interface. + + Submit a USB get HID report descriptor request for the USB device specified by + UsbIo and Interface and return the report descriptor in DescriptorBuffer. + If UsbIo is NULL, then ASSERT(). + If DescriptorBuffer is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param DescriptorLength The size, in bytes, of DescriptorBuffer. + @param DescriptorBuffer A pointer to the buffer to store the report class descriptor. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed because the + buffer specified by DescriptorLength and DescriptorBuffer + is not large enough to hold the result of the request. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbGetReportDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT16 DescriptorLength, + OUT UINT8 *DescriptorBuffer + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + ASSERT (DescriptorBuffer != NULL); + + // + // Fill Device request packet + // + Request.RequestType = USB_HID_GET_DESCRIPTOR_REQ_TYPE; + Request.Request = USB_REQ_GET_DESCRIPTOR; + Request.Value = (UINT16) (USB_DESC_TYPE_REPORT << 8); + Request.Index = Interface; + Request.Length = DescriptorLength; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + DescriptorBuffer, + DescriptorLength, + &Status + ); + + return Result; + +} + +/** + Get the HID protocol of the specified USB HID interface. + + Submit a USB get HID protocol request for the USB device specified by UsbIo + and Interface and return the protocol retrieved in Protocol. + If UsbIo is NULL, then ASSERT(). + If Protocol is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param Protocol A pointer to the protocol for the specified USB target. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbGetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + OUT UINT8 *Protocol + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + ASSERT (Protocol != NULL); + + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE; + Request.Request = EFI_USB_GET_PROTOCOL_REQUEST; + Request.Value = 0; + Request.Index = Interface; + Request.Length = 1; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + Protocol, + sizeof (UINT8), + &Status + ); + + return Result; +} + + + +/** + Set the HID protocol of the specified USB HID interface. + + Submit a USB set HID protocol request for the USB device specified by UsbIo + and Interface and set the protocol to the value specified by Protocol. + If UsbIo is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param Protocol The protocol value to set for the specified USB target. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbSetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 Protocol + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE; + Request.Request = EFI_USB_SET_PROTOCOL_REQUEST; + Request.Value = Protocol; + Request.Index = Interface; + Request.Length = 0; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + &Status + ); + return Result; +} + + +/** + Set the idle rate of the specified USB HID report. + + Submit a USB set HID report idle request for the USB device specified by UsbIo, + Interface, and ReportId, and set the idle rate to the value specified by Duration. + If UsbIo is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param ReportId The identifier of the report to retrieve. + @param Duration The idle rate to set for the specified USB target. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbSetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 Duration + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE; + Request.Request = EFI_USB_SET_IDLE_REQUEST; + Request.Value = (UINT16) ((Duration << 8) | ReportId); + Request.Index = Interface; + Request.Length = 0; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + &Status + ); + return Result; +} + + +/** + Get the idle rate of the specified USB HID report. + + Submit a USB get HID report idle request for the USB device specified by UsbIo, + Interface, and ReportId, and return the ide rate in Duration. + If UsbIo is NULL, then ASSERT(). + If Duration is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param ReportId The identifier of the report to retrieve. + @param Duration A pointer to the idle rate retrieved from the specified USB target. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbGetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + OUT UINT8 *Duration + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + ASSERT (Duration != NULL); + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE; + Request.Request = EFI_USB_GET_IDLE_REQUEST; + Request.Value = ReportId; + Request.Index = Interface; + Request.Length = 1; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + Duration, + 1, + &Status + ); + + return Result; +} + + + +/** + Set the report descriptor of the specified USB HID interface. + + Submit a USB set HID report request for the USB device specified by UsbIo, + Interface, ReportId, and ReportType, and set the report descriptor using the + buffer specified by ReportLength and Report. + If UsbIo is NULL, then ASSERT(). + If Report is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param ReportId The identifier of the report to retrieve. + @param ReportType The type of report to retrieve. + @param ReportLength The size, in bytes, of Report. + @param Report A pointer to the report descriptor buffer to set. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbSetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + IN UINT8 *Report + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + ASSERT (Report != NULL); + + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE; + Request.Request = EFI_USB_SET_REPORT_REQUEST; + Request.Value = (UINT16) ((ReportType << 8) | ReportId); + Request.Index = Interface; + Request.Length = ReportLen; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + PcdGet32 (PcdUsbTransferTimeoutValue), + Report, + ReportLen, + &Status + ); + + return Result; +} + + +/** + Get the report descriptor of the specified USB HID interface. + + Submit a USB get HID report request for the USB device specified by UsbIo, + Interface, ReportId, and ReportType, and return the report in the buffer + specified by Report. + If UsbIo is NULL, then ASSERT(). + If Report is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The index of the report interface on the USB target. + @param ReportId The identifier of the report to retrieve. + @param ReportType The type of report to retrieve. + @param ReportLength The size, in bytes, of Report. + @param Report A pointer to the buffer to store the report descriptor. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed because the + buffer specified by ReportLength and Report is not + large enough to hold the result of the request. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + +**/ +EFI_STATUS +EFIAPI +UsbGetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + OUT UINT8 *Report + ) +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + ASSERT (UsbIo != NULL); + ASSERT (Report != NULL); + + // + // Fill Device request packet + // + Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE; + Request.Request = EFI_USB_GET_REPORT_REQUEST; + Request.Value = (UINT16) ((ReportType << 8) | ReportId); + Request.Index = Interface; + Request.Length = ReportLen; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + Report, + ReportLen, + &Status + ); + + return Result; +} diff --git a/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf new file mode 100644 index 000000000..bb483b922 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf @@ -0,0 +1,43 @@ +## @file +# Uefi Usb Library instance. +# +# This library instance provides most usb APIs to support the Hid requests defined in +# Usb Hid 1.1 spec and the standard requests defined in Usb 1.1 spec. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiUsbLib + MODULE_UNI_FILE = UefiUsbLib.uni + FILE_GUID = 87eb5df9-722a-4241-ad7f-370d0b3a56d7 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiUsbLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiUsbLibInternal.h + Hid.c + UsbDxeLib.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + PcdLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue ## CONSUMES + diff --git a/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni new file mode 100644 index 000000000..c0ebeaf20 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Uefi Usb Library instance. +// +// This library instance provides most usb APIs to support the Hid requests defined in +// Usb Hid 1.1 spec and the standard requests defined in Usb 1.1 spec. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI USB Library instance" + +#string STR_MODULE_DESCRIPTION #language en-US "This library instance provides most USB APIs to support the HID requests defined in the USB HID 1.1 specification and the standard requests defined in the USB 1.1 specification." + diff --git a/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h new file mode 100644 index 000000000..5909d96e9 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h @@ -0,0 +1,24 @@ +/** @file + + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _UEFI_USB_LIB_INTERNAL_H_ +#define _UEFI_USB_LIB_INTERNAL_H_ + +#include + +#include +#include +#include +#include + +#include + + +#endif diff --git a/roms/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c b/roms/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c new file mode 100644 index 000000000..e75df8d04 --- /dev/null +++ b/roms/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c @@ -0,0 +1,665 @@ +/** @file + + The library provides the USB Standard Device Requests defined + in Usb specification 9.4 section. + + Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiUsbLibInternal.h" + + +/** + Get the descriptor of the specified USB device. + + Submit a USB get descriptor request for the USB device specified by UsbIo, Value, + and Index, and return the descriptor in the buffer specified by Descriptor. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Descriptor is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Value The device request value. + @param Index The device request index. + @param DescriptorLength The size, in bytes, of Descriptor. + @param Descriptor A pointer to the descriptor buffer to get. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed because the + buffer specified by DescriptorLength and Descriptor + is not large enough to hold the result of the request. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. The transfer + status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbGetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + OUT VOID *Descriptor, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Descriptor != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE; + DevReq.Request = USB_REQ_GET_DESCRIPTOR; + DevReq.Value = Value; + DevReq.Index = Index; + DevReq.Length = DescriptorLength; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + Descriptor, + DescriptorLength, + Status + ); +} + + +/** + Set the descriptor of the specified USB device. + + Submit a USB set descriptor request for the USB device specified by UsbIo, + Value, and Index, and set the descriptor using the buffer specified by DesriptorLength + and Descriptor. The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Descriptor is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Value The device request value. + @param Index The device request index. + @param DescriptorLength The size, in bytes, of Descriptor. + @param Descriptor A pointer to the descriptor buffer to set. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbSetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + IN VOID *Descriptor, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Descriptor != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_DESCRIPTOR_REQ_TYPE; + DevReq.Request = USB_REQ_SET_DESCRIPTOR; + DevReq.Value = Value; + DevReq.Index = Index; + DevReq.Length = DescriptorLength; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataOut, + PcdGet32 (PcdUsbTransferTimeoutValue), + Descriptor, + DescriptorLength, + Status + ); +} + + +/** + Get the interface setting of the specified USB device. + + Submit a USB get interface request for the USB device specified by UsbIo, + and Interface, and place the result in the buffer specified by AlternateSetting. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If AlternateSetting is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The interface index value. + @param AlternateSetting A pointer to the alternate setting to be retrieved. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbGetInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Interface, + OUT UINT16 *AlternateSetting, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (AlternateSetting != NULL); + ASSERT (Status != NULL); + + *AlternateSetting = 0; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_INTERFACE_REQ_TYPE; + DevReq.Request = USB_REQ_GET_INTERFACE; + DevReq.Index = Interface; + DevReq.Length = 1; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + AlternateSetting, + 1, + Status + ); +} + + +/** + Set the interface setting of the specified USB device. + + Submit a USB set interface request for the USB device specified by UsbIo, and + Interface, and set the alternate setting to the value specified by AlternateSetting. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Interface The interface index value. + @param AlternateSetting The alternate setting to be set. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_SUCCESS The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbSetInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Interface, + IN UINT16 AlternateSetting, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_INTERFACE_REQ_TYPE; + DevReq.Request = USB_REQ_SET_INTERFACE; + DevReq.Value = AlternateSetting; + DevReq.Index = Interface; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + Status + ); +} + + +/** + Get the device configuration. + + Submit a USB get configuration request for the USB device specified by UsbIo + and place the result in the buffer specified by ConfigurationValue. The status + of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If ConfigurationValue is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param ConfigurationValue A pointer to the device configuration to be retrieved. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbGetConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT16 *ConfigurationValue, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (ConfigurationValue != NULL); + ASSERT (Status != NULL); + + *ConfigurationValue = 0; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_CONFIGURATION_REQ_TYPE; + DevReq.Request = USB_REQ_GET_CONFIG; + DevReq.Length = 1; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + ConfigurationValue, + 1, + Status + ); +} + + +/** + Set the device configuration. + + Submit a USB set configuration request for the USB device specified by UsbIo + and set the device configuration to the value specified by ConfigurationValue. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param ConfigurationValue The device configuration value to be set. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbSetConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 ConfigurationValue, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE; + DevReq.Request = USB_REQ_SET_CONFIG; + DevReq.Value = ConfigurationValue; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + Status + ); +} + + +/** + Set the specified feature of the specified device. + + Submit a USB set device feature request for the USB device specified by UsbIo, + Recipient, and Target to the value specified by Value. The status of the + transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). + Type USB_TYPES_DEFINITION is defined in the MDE Package Industry + Standard include file Usb.h. + @param Value The value of the feature to be set. + @param Target The index of the device to be set. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbSetFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN USB_TYPES_DEFINITION Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case USB_TARGET_DEVICE: + DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_D; + break; + + case USB_TARGET_INTERFACE: + DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_I; + break; + + case USB_TARGET_ENDPOINT: + DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_E; + break; + + default: + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_REQ_SET_FEATURE; + DevReq.Value = Value; + DevReq.Index = Target; + + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + Status + ); +} + + +/** + Clear the specified feature of the specified device. + + Submit a USB clear device feature request for the USB device specified by UsbIo, + Recipient, and Target to the value specified by Value. The status of the transfer + is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). + Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard + include file Usb.h. + @param Value The value of the feature to be cleared. + @param Target The index of the device to be cleared. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbClearFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN USB_TYPES_DEFINITION Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (Status != NULL); + + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case USB_TARGET_DEVICE: + DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D; + break; + + case USB_TARGET_INTERFACE: + DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I; + break; + + case USB_TARGET_ENDPOINT: + DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E; + break; + + default: + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_REQ_CLEAR_FEATURE; + DevReq.Value = Value; + DevReq.Index = Target; + + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + PcdGet32 (PcdUsbTransferTimeoutValue), + NULL, + 0, + Status + ); +} + + +/** + Get the status of the specified device. + + Submit a USB device get status request for the USB device specified by UsbIo, + Recipient, and Target and place the result in the buffer specified by DeviceStatus. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If DeviceStatus is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). + Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard + include file Usb.h. + @param Target The index of the device to be get the status of. + @param DeviceStatus A pointer to the device status to be retrieved. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + +**/ +EFI_STATUS +EFIAPI +UsbGetStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN USB_TYPES_DEFINITION Recipient, + IN UINT16 Target, + OUT UINT16 *DeviceStatus, + OUT UINT32 *Status + ) +{ + EFI_USB_DEVICE_REQUEST DevReq; + + ASSERT (UsbIo != NULL); + ASSERT (DeviceStatus != NULL); + ASSERT (Status != NULL); + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case USB_TARGET_DEVICE: + DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_D; + break; + + case USB_TARGET_INTERFACE: + DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_I; + break; + + case USB_TARGET_ENDPOINT: + DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_E; + break; + + default: + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_REQ_GET_STATUS; + DevReq.Value = 0; + DevReq.Index = Target; + DevReq.Length = 2; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + PcdGet32 (PcdUsbTransferTimeoutValue), + DeviceStatus, + 2, + Status + ); +} + + +/** + Clear halt feature of the specified usb endpoint. + + Retrieve the USB endpoint descriptor specified by UsbIo and EndPoint. + If the USB endpoint descriptor can not be retrieved, then return EFI_NOT_FOUND. + If the endpoint descriptor is found, then clear the halt feature of this USB endpoint. + The status of the transfer is returned in Status. + If UsbIo is NULL, then ASSERT(). + If Status is NULL, then ASSERT(). + + @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. + @param Endpoint The endpoint address. + @param Status A pointer to the status of the transfer. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + The transfer status is returned in Status. + @retval EFI_NOT_FOUND The specified USB endpoint descriptor can not be found + +**/ +EFI_STATUS +EFIAPI +UsbClearEndpointHalt ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + OUT UINT32 *Status + ) +{ + EFI_STATUS Result; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + UINT8 Index; + + ASSERT (UsbIo != NULL); + ASSERT (Status != NULL); + + ZeroMem (&EndpointDescriptor, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)); + // + // First search the endpoint descriptor for that endpoint addr + // + Result = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Result)) { + return Result; + } + + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + Result = UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + if (EFI_ERROR (Result)) { + continue; + } + + if (EndpointDescriptor.EndpointAddress == Endpoint) { + break; + } + } + + if (Index == InterfaceDescriptor.NumEndpoints) { + // + // No such endpoint + // + return EFI_NOT_FOUND; + } + + Result = UsbClearFeature ( + UsbIo, + USB_TARGET_ENDPOINT, + USB_FEATURE_ENDPOINT_HALT, + EndpointDescriptor.EndpointAddress, + Status + ); + + return Result; +} -- cgit 1.2.3-korg